From f6fa3d6f48431a4fe140d1ba125c6a6c2967c69c Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 10:12:44 -0400 Subject: [PATCH 01/12] initial live validation --- packages/manager/package.json | 1 + .../manager/src/components/VLANSelect.tsx | 7 +++- .../Linodes/LinodeCreatev2/Access.tsx | 2 + .../LinodeCreatev2/Details/Details.tsx | 2 + .../Linodes/LinodeCreatev2/Firewall.tsx | 1 + .../LinodeCreatev2/Tabs/Distributions.tsx | 1 + .../Linodes/LinodeCreatev2/Tabs/Images.tsx | 1 + .../LinodeCreatev2/UserData/UserData.tsx | 10 +++-- .../features/Linodes/LinodeCreatev2/VLAN.tsx | 3 ++ .../Linodes/LinodeCreatev2/VPC/VPC.tsx | 4 ++ .../Linodes/LinodeCreatev2/VPC/VPCRanges.tsx | 2 + .../features/Linodes/LinodeCreatev2/index.tsx | 8 +++- .../Linodes/LinodeCreatev2/utilities.ts | 40 +++++++++++++++---- 13 files changed, 68 insertions(+), 14 deletions(-) diff --git a/packages/manager/package.json b/packages/manager/package.json index 95ba61b9112..8a7751e8327 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -16,6 +16,7 @@ "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@hookform/resolvers": "2.9.11", "@linode/api-v4": "*", "@linode/validation": "*", "@lukemorales/query-key-factory": "^1.3.4", diff --git a/packages/manager/src/components/VLANSelect.tsx b/packages/manager/src/components/VLANSelect.tsx index e739410821d..98b47a78668 100644 --- a/packages/manager/src/components/VLANSelect.tsx +++ b/packages/manager/src/components/VLANSelect.tsx @@ -21,6 +21,10 @@ interface Props { * Default API filter */ filter?: Filter; + /** + * Called when the field is blured + */ + onBlur?: () => void; /** * Is called when a VLAN is selected */ @@ -42,7 +46,7 @@ interface Props { * - Allows VLAN creation */ export const VLANSelect = (props: Props) => { - const { disabled, errorText, filter, onChange, sx, value } = props; + const { disabled, errorText, filter, onBlur, onChange, sx, value } = props; const [open, setOpen] = React.useState(false); const [inputValue, setInputValue] = useState(''); @@ -124,6 +128,7 @@ export const VLANSelect = (props: Props) => { label="VLAN" loading={isFetching} noOptionsText="You have no VLANs in this region. Type to create one." + onBlur={onBlur} open={open} options={vlans} placeholder="Create or select a VLAN" diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Access.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Access.tsx index 1daa81d6edd..ce033562c43 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Access.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Access.tsx @@ -32,9 +32,11 @@ export const Access = () => { autoComplete="off" disabled={isLinodeCreateRestricted} errorText={fieldState.error?.message} + inputRef={field.ref} label="Root Password" name="password" noMarginTop + onBlur={field.onBlur} onChange={field.onChange} placeholder="Enter a password." value={field.value ?? ''} diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Details/Details.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Details/Details.tsx index ed1fc1b205a..06ba195494c 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Details/Details.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Details/Details.tsx @@ -29,7 +29,9 @@ export const Details = () => { diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Firewall.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Firewall.tsx index 4188f6581ad..df56b2998b9 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Firewall.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Firewall.tsx @@ -48,6 +48,7 @@ export const Firewall = () => { label="Assign Firewall" loading={isLoading} noMarginTop + onBlur={field.onBlur} onChange={(e, firewall) => field.onChange(firewall?.id ?? null)} options={firewalls ?? []} placeholder="None" diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Distributions.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Distributions.tsx index 67fb49eef7f..8306b1adf5d 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Distributions.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Distributions.tsx @@ -23,6 +23,7 @@ export const Distributions = () => { field.onChange(image?.id ?? null)} value={field.value} variant="public" diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Images.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Images.tsx index 84ccb844c03..3e766b86341 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Images.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Tabs/Images.tsx @@ -23,6 +23,7 @@ export const Images = () => { field.onChange(image?.id ?? null)} value={field.value} variant="private" diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/UserData/UserData.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/UserData/UserData.tsx index 982c57bb7b1..e570a4f0013 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/UserData/UserData.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/UserData/UserData.tsx @@ -80,22 +80,24 @@ export const UserData = () => { ( + onBlur={(e) => { + field.onBlur(); checkFormat({ hasInputValueChanged: false, userData: e.target.value, - }) - } + }); + }} onChange={(e) => { + field.onChange(e); checkFormat({ hasInputValueChanged: true, userData: e.target.value, }); - field.onChange(e); }} disabled={isLinodeCreateRestricted} errorText={fieldState.error?.message} expand + inputRef={field.ref} label="User Data" labelTooltipText="Compatible formats include cloud-config data and executable scripts." multiline diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx index 6dc1ee78999..f6e3f13497a 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx @@ -86,6 +86,7 @@ export const VLAN = () => { disabled={disabled} errorText={fieldState.error?.message} filter={{ region: regionId }} + onBlur={field.onBlur} onChange={field.onChange} sx={{ minWidth: 300 }} value={field.value ?? null} @@ -102,7 +103,9 @@ export const VLAN = () => { } disabled={disabled} errorText={fieldState.error?.message} + inputRef={field.ref} label="IPAM Address" + onBlur={field.onBlur} onChange={field.onChange} optional placeholder="192.0.2.0/24" diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx index 48c4f49b85e..e6fb910ac61 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx @@ -133,9 +133,11 @@ export const VPC = () => { errorText={fieldState.error?.message} label="Subnet" noMarginTop + onBlur={field.onBlur} onChange={(e, subnet) => field.onChange(subnet?.id ?? null)} options={selectedVPC?.subnets ?? []} placeholder="Select Subnet" + ref={field.ref} /> )} control={control} @@ -183,7 +185,9 @@ export const VPC = () => { render={({ field, fieldState }) => ( { { - const methods = useForm({ defaultValues }); + const methods = useForm({ + defaultValues, + mode: 'onBlur', + resolver, + }); + const history = useHistory(); const { mutateAsync: createLinode } = useCreateLinodeMutation(); diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts index 3e1403086af..2d8737e9b87 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts @@ -1,3 +1,5 @@ +import { yupResolver } from '@hookform/resolvers/yup'; +import { CreateLinodeSchema } from '@linode/validation'; import { useHistory } from 'react-router-dom'; import { getQueryParamsFromQueryString } from 'src/utilities/queryParams'; @@ -6,6 +8,7 @@ import { utoa } from '../LinodesCreate/utilities'; import type { LinodeCreateType } from '../LinodesCreate/types'; import type { CreateLinodeRequest, InterfacePayload } from '@linode/api-v4'; +import type { Resolver } from 'react-hook-form'; /** * This interface is used to type the query params on the Linode Create flow. @@ -74,20 +77,21 @@ export const tabs: LinodeCreateType[] = [ export const getLinodeCreatePayload = ( payload: CreateLinodeRequest ): CreateLinodeRequest => { - if (payload.metadata?.user_data) { - payload.metadata.user_data = utoa(payload.metadata.user_data); + const values = { ...payload }; + if (values.metadata?.user_data) { + values.metadata.user_data = utoa(values.metadata.user_data); } - if (!payload.metadata?.user_data) { - payload.metadata = undefined; + if (!values.metadata?.user_data) { + values.metadata = undefined; } - payload.interfaces = getInterfacesPayload( - payload.interfaces, - Boolean(payload.private_ip) + values.interfaces = getInterfacesPayload( + values.interfaces, + Boolean(values.private_ip) ); - return payload; + return values; }; /** @@ -161,3 +165,23 @@ export const defaultValues: CreateLinodeRequest = { region: '', type: '', }; + +/** + * Provides dynamic validation to the Linode Create form. + * + * Unfortunately, we have to wrap `yupResolver` so that we can transform the payload + * using `getLinodeCreatePayload` before validaton happens. + */ +export const resolver: Resolver = ( + values, + context, + options +) => { + const transformedValues = getLinodeCreatePayload(values); + + return yupResolver(CreateLinodeSchema, {}, { rawValues: true })( + transformedValues, + context, + options + ); +}; From b19935d2053bde011426867d13709c1b71663746 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 10:13:25 -0400 Subject: [PATCH 02/12] initial live validation --- yarn.lock | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/yarn.lock b/yarn.lock index 878b7763065..30739364956 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1817,6 +1817,11 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== +"@hookform/resolvers@2.9.11": + version "2.9.11" + resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.11.tgz#9ce96e7746625a89239f68ca57c4f654264c17ef" + integrity sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ== + "@humanwhocodes/config-array@^0.11.13": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" From 660f42a1fa46c33528f36c4b5b147e307f77e571 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 10:47:22 -0400 Subject: [PATCH 03/12] fix unit test failure --- .../src/features/Linodes/LinodeCreatev2/utilities.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.test.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.test.tsx index 0651af3fde3..fb614917f88 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.test.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.test.tsx @@ -24,7 +24,7 @@ describe('getLinodeCreatePayload', () => { it('should return a basic payload', () => { const values = createLinodeRequestFactory.build(); - expect(getLinodeCreatePayload(values)).toStrictEqual(values); + expect(getLinodeCreatePayload(values)).toEqual(values); }); it('should base64 encode metadata', () => { @@ -32,7 +32,7 @@ describe('getLinodeCreatePayload', () => { metadata: { user_data: userData }, }); - expect(getLinodeCreatePayload(values)).toStrictEqual({ + expect(getLinodeCreatePayload(values)).toEqual({ ...values, metadata: { user_data: base64UserData }, }); From 38a8e6c476f5c7b9c2a11d4dd41849481cfb0492 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 11:14:41 -0400 Subject: [PATCH 04/12] focus region select on error --- .../manager/src/components/RegionSelect/RegionSelect.tsx | 1 + .../src/components/SelectRegionPanel/SelectRegionPanel.tsx | 4 ++++ .../manager/src/features/Linodes/LinodeCreatev2/Region.tsx | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/packages/manager/src/components/RegionSelect/RegionSelect.tsx b/packages/manager/src/components/RegionSelect/RegionSelect.tsx index 763c1a83157..55eb20c369c 100644 --- a/packages/manager/src/components/RegionSelect/RegionSelect.tsx +++ b/packages/manager/src/components/RegionSelect/RegionSelect.tsx @@ -125,6 +125,7 @@ export const RegionSelect = React.memo((props: RegionSelectProps) => { }, })} textFieldProps={{ + ...props.textFieldProps, InputProps: { endAdornment: regionFilter !== 'core' && selectedRegion?.site_type === 'edge' && ( diff --git a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx index 0fb480ff6a7..407018317c1 100644 --- a/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx +++ b/packages/manager/src/components/SelectRegionPanel/SelectRegionPanel.tsx @@ -26,8 +26,10 @@ import { DocsLink } from '../DocsLink/DocsLink'; import { Link } from '../Link'; import type { LinodeCreateType } from 'src/features/Linodes/LinodesCreate/types'; +import { RegionSelectProps } from '../RegionSelect/RegionSelect.types'; interface SelectRegionPanelProps { + RegionSelectProps?: Partial; currentCapability: Capabilities; disabled?: boolean; error?: string; @@ -49,6 +51,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => { helperText, selectedId, selectedLinodeTypeId, + RegionSelectProps, } = props; const flags = useFlags(); @@ -147,6 +150,7 @@ export const SelectRegionPanel = (props: SelectRegionPanelProps) => { regions={regions ?? []} selectedId={selectedId || null} showEdgeIconHelperText={showEdgeIconHelperText} + {...RegionSelectProps} /> {showClonePriceWarning && ( { return ( Date: Fri, 12 Apr 2024 11:22:59 -0400 Subject: [PATCH 05/12] dial in some styles and refs --- .../src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx | 8 ++++++-- .../src/features/Linodes/LinodeCreatev2/VPC/VPCRanges.tsx | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx index e6fb910ac61..ec6b7108723 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx @@ -92,6 +92,7 @@ export const VPC = () => { : undefined } textFieldProps={{ + inputRef: field.ref, sx: (theme) => ({ [theme.breakpoints.up('sm')]: { minWidth: inputMaxWidth }, }), @@ -125,6 +126,9 @@ export const VPC = () => { getOptionLabel={(subnet) => `${subnet.label} (${subnet.ipv4})` } + textFieldProps={{ + inputRef: field.ref, + }} value={ selectedVPC?.subnets.find( (subnet) => subnet.id === field.value @@ -137,7 +141,6 @@ export const VPC = () => { onChange={(e, subnet) => field.onChange(subnet?.id ?? null)} options={selectedVPC?.subnets ?? []} placeholder="Select Subnet" - ref={field.ref} /> )} control={control} @@ -184,13 +187,14 @@ export const VPC = () => { ( )} diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPCRanges.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPCRanges.tsx index 4a85fd947d6..fedb35aa619 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPCRanges.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPCRanges.tsx @@ -37,6 +37,7 @@ export const VPCRanges = () => { onBlur={field.onBlur} onChange={field.onChange} placeholder="10.0.0.0/24" + sx={{ minWidth: 290 }} value={field.value} /> )} From 88cac56a8097916985d5bc66334434acc613aaea Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 11:35:11 -0400 Subject: [PATCH 06/12] Added changeset: Linode Create Refactor - Validation --- .../.changeset/pr-10374-upcoming-features-1712936111438.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-10374-upcoming-features-1712936111438.md diff --git a/packages/manager/.changeset/pr-10374-upcoming-features-1712936111438.md b/packages/manager/.changeset/pr-10374-upcoming-features-1712936111438.md new file mode 100644 index 00000000000..86db3d4dd48 --- /dev/null +++ b/packages/manager/.changeset/pr-10374-upcoming-features-1712936111438.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Linode Create Refactor - Validation ([#10374](https://github.com/linode/manager/pull/10374)) From 4c2679a732169ee8a07d041f99b50accc678c5cc Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 11:45:50 -0400 Subject: [PATCH 07/12] improve vpc validation --- packages/validation/src/linodes.schema.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/validation/src/linodes.schema.ts b/packages/validation/src/linodes.schema.ts index 673c46d6c18..b9a71269c4c 100644 --- a/packages/validation/src/linodes.schema.ts +++ b/packages/validation/src/linodes.schema.ts @@ -173,7 +173,9 @@ export const LinodeInterfaceSchema = object().shape({ primary: boolean().notRequired(), subnet_id: number().when('purpose', { is: 'vpc', - then: number().required('Subnet is required.'), + then: number() + .transform((value) => (isNaN(value) ? undefined : value)) + .required('Subnet is required.'), otherwise: number().test({ name: testnameDisallowedBasedOnPurpose('VPC'), message: testmessageDisallowedBasedOnPurpose('vpc', 'subnet_id'), From b89f4746c33b15bf0a4f91edd5179e4fdb5fbc77 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Fri, 12 Apr 2024 12:10:08 -0400 Subject: [PATCH 08/12] fixes --- .../Linodes/LinodeCreatev2/VPC/VPC.tsx | 6 ++++++ .../Linodes/LinodeCreatev2/utilities.ts | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx index ec6b7108723..4c5a44e4a6f 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VPC/VPC.tsx @@ -248,6 +248,12 @@ export const VPC = () => { . + {formState.errors.interfaces?.[0]?.ip_ranges?.message && ( + + )} )} diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts index 2d8737e9b87..89170e525c4 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts @@ -172,16 +172,22 @@ export const defaultValues: CreateLinodeRequest = { * Unfortunately, we have to wrap `yupResolver` so that we can transform the payload * using `getLinodeCreatePayload` before validaton happens. */ -export const resolver: Resolver = ( +export const resolver: Resolver = async ( values, context, options ) => { const transformedValues = getLinodeCreatePayload(values); - return yupResolver(CreateLinodeSchema, {}, { rawValues: true })( - transformedValues, - context, - options - ); + const { errors } = await yupResolver( + CreateLinodeSchema, + {}, + { rawValues: true } + )(transformedValues, context, options); + + if (errors) { + return { errors, values }; + } + + return { errors: {}, values }; }; From 08b16d7e4caf0048a705ae8b91a29ba466408622 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Tue, 16 Apr 2024 14:21:27 -0400 Subject: [PATCH 09/12] spelling fixes --- packages/manager/src/components/VLANSelect.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/components/VLANSelect.tsx b/packages/manager/src/components/VLANSelect.tsx index 98b47a78668..99d5fe82996 100644 --- a/packages/manager/src/components/VLANSelect.tsx +++ b/packages/manager/src/components/VLANSelect.tsx @@ -22,7 +22,7 @@ interface Props { */ filter?: Filter; /** - * Called when the field is blured + * Called when the field is blurred */ onBlur?: () => void; /** From f8e622162c4c34d725e425d6b72cc3033987e16b Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Tue, 16 Apr 2024 14:37:02 -0400 Subject: [PATCH 10/12] surface interface API error as a general error --- .../src/features/Linodes/LinodeCreatev2/Error.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/Error.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/Error.tsx index 866fb1a314a..70ae45379a1 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/Error.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/Error.tsx @@ -8,16 +8,20 @@ import { Paper } from 'src/components/Paper'; import type { CreateLinodeRequest } from '@linode/api-v4'; export const Error = () => { - const { formState } = useFormContext(); + const { + formState: { errors }, + } = useFormContext(); - if (!formState.errors.root?.message) { + const generalError = errors.root?.message ?? errors.interfaces?.message; + + if (!generalError) { return null; } return ( - {formState.errors.root.message} + {generalError} ); From fc5c24815da1b1574c26f48da44dd61bbb234d01 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Tue, 16 Apr 2024 14:52:31 -0400 Subject: [PATCH 11/12] improve VLANs wrapping --- packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx b/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx index f6e3f13497a..1cae85da5ed 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/VLAN.tsx @@ -88,7 +88,7 @@ export const VLAN = () => { filter={{ region: regionId }} onBlur={field.onBlur} onChange={field.onChange} - sx={{ minWidth: 300 }} + sx={{ width: 300 }} value={field.value ?? null} /> )} @@ -101,6 +101,7 @@ export const VLAN = () => { tooltipText={ 'IPAM address must use IP/netmask format, e.g. 192.0.2.0/24.' } + containerProps={{ maxWidth: 335 }} disabled={disabled} errorText={fieldState.error?.message} inputRef={field.ref} @@ -109,7 +110,6 @@ export const VLAN = () => { onChange={field.onChange} optional placeholder="192.0.2.0/24" - sx={{ maxWidth: 300 }} value={field.value ?? ''} /> )} From ccf3595ae0994ca37e3cebac06c37d676d350834 Mon Sep 17 00:00:00 2001 From: Banks Nussman Date: Tue, 16 Apr 2024 18:51:32 -0400 Subject: [PATCH 12/12] fix typo --- .../manager/src/features/Linodes/LinodeCreatev2/utilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts index 89170e525c4..34cde1fe1e5 100644 --- a/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts +++ b/packages/manager/src/features/Linodes/LinodeCreatev2/utilities.ts @@ -170,7 +170,7 @@ export const defaultValues: CreateLinodeRequest = { * Provides dynamic validation to the Linode Create form. * * Unfortunately, we have to wrap `yupResolver` so that we can transform the payload - * using `getLinodeCreatePayload` before validaton happens. + * using `getLinodeCreatePayload` before validation happens. */ export const resolver: Resolver = async ( values,