From 570713bc2d0d4409320acf17e989545e6cf6425f Mon Sep 17 00:00:00 2001 From: smans-akamai Date: Wed, 1 Oct 2025 12:14:33 -0400 Subject: [PATCH 1/2] fix: [UIE-9294] - DBaaS - Database Create Subnet field should display backend error messages (#12930) * fix: [UIE-9294] - DBaaS - Database Create Subnet field should display backend error messages * Adding validation error text for Public Access field in DatbaseVPCSelector * Applying feedback on unecessary conditional check with .includes * clean up * Updating handleAPIErrors to accept a check function * updating comment * Applying additional feedback and updating changelog date --------- Co-authored-by: Hana Xu --- packages/manager/CHANGELOG.md | 6 ++++ packages/manager/package.json | 2 +- .../DatabaseCreate/DatabaseCreate.tsx | 3 +- .../DatabaseCreate/DatabaseVPCSelector.tsx | 11 ++++++ .../src/utilities/formikErrorUtils.test.ts | 34 +++++++++++++++++-- .../manager/src/utilities/formikErrorUtils.ts | 25 ++++++++++++-- 6 files changed, 75 insertions(+), 6 deletions(-) diff --git a/packages/manager/CHANGELOG.md b/packages/manager/CHANGELOG.md index 23d07c71a98..4ac1ca61e2c 100644 --- a/packages/manager/CHANGELOG.md +++ b/packages/manager/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2025-10-01] - v1.151.2 + +### Fixed: + +- DBaaS - Database Create Subnet field should display backend error messages + ## [2025-09-25] - v1.151.1 ### Added: diff --git a/packages/manager/package.json b/packages/manager/package.json index a4c5b63df94..2ce25a30033 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -2,7 +2,7 @@ "name": "linode-manager", "author": "Linode", "description": "The Linode Manager website", - "version": "1.151.1", + "version": "1.151.2", "private": true, "type": "module", "bugs": { diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx index bfa7234fbfd..15080cb3e19 100644 --- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx +++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx @@ -162,7 +162,8 @@ export const DatabaseCreate = () => { if (ipErrors) { setIPErrorsFromAPI(ipErrors); } - handleAPIErrors(errors, setFieldError, setCreateError); + const parentFields = ['private_network']; // List of parent fields that need the full key from the errors response + handleAPIErrors(errors, setFieldError, setCreateError, parentFields); } setSubmitting(false); diff --git a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseVPCSelector.tsx b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseVPCSelector.tsx index ff8ae035028..0df9bd13875 100644 --- a/packages/manager/src/features/Databases/DatabaseCreate/DatabaseVPCSelector.tsx +++ b/packages/manager/src/features/Databases/DatabaseCreate/DatabaseVPCSelector.tsx @@ -4,6 +4,7 @@ import { BetaChip, Box, Checkbox, + FormHelperText, Notice, TooltipIcon, Typography, @@ -209,6 +210,16 @@ export const DatabaseVPCSelector = (props: DatabaseVPCSelectorProps) => { 'Adds a public endpoint to the database in addition to the private VPC endpoint.' } /> + {errors?.private_network?.public_access && ( + + {errors?.private_network?.public_access} + + )} ) : ( diff --git a/packages/manager/src/utilities/formikErrorUtils.test.ts b/packages/manager/src/utilities/formikErrorUtils.test.ts index 11bc89e5d45..6a27eddd9bf 100644 --- a/packages/manager/src/utilities/formikErrorUtils.test.ts +++ b/packages/manager/src/utilities/formikErrorUtils.test.ts @@ -17,7 +17,17 @@ const setFieldError = vi.fn(); const setError = vi.fn(); describe('handleAPIErrors', () => { - it('should handle api error with a field', () => { + it('should handle API error for a regular field', () => { + const errorWithFlatField = [{ field: 'label', reason: 'Invalid label' }]; + handleAPIErrors(errorWithFlatField, setFieldError, setError); + expect(setFieldError).toHaveBeenCalledWith( + 'label', + errorWithFlatField[0].reason + ); + expect(setError).not.toHaveBeenCalled(); + }); + + it('should handle API error for a parent field when parentFields is not provided', () => { handleAPIErrors(errorWithField, setFieldError, setError); expect(setFieldError).toHaveBeenCalledWith( 'card_number', @@ -26,7 +36,27 @@ describe('handleAPIErrors', () => { expect(setError).not.toHaveBeenCalled(); }); - it('should handle a general api error', () => { + it('should handle API error for a parent field when parentFields is provided', () => { + const errorWithParentField = [ + { field: 'private_network.subnet_id', reason: 'Invalid subnet ID' }, + ]; + + const parentFields = ['private_network']; // Provide parentFields so full field key is used + + handleAPIErrors( + errorWithParentField, + setFieldError, + setError, + parentFields + ); + expect(setFieldError).toHaveBeenCalledWith( + 'private_network.subnet_id', + errorWithParentField[0].reason + ); + expect(setError).not.toHaveBeenCalled(); + }); + + it('should handle a general API error', () => { handleAPIErrors(errorWithoutField, setFieldError, setError); expect(setFieldError).not.toHaveBeenCalledWith(); expect(setError).toHaveBeenCalledWith(errorWithoutField[0].reason); diff --git a/packages/manager/src/utilities/formikErrorUtils.ts b/packages/manager/src/utilities/formikErrorUtils.ts index ce2f5c7079e..e465d8b4507 100644 --- a/packages/manager/src/utilities/formikErrorUtils.ts +++ b/packages/manager/src/utilities/formikErrorUtils.ts @@ -122,10 +122,25 @@ export const handleGeneralErrors = ( } }; +/** + * This function checks if the parent field from the APIError object is included + * in parentFields list and returns true if if it's found. + * This check will determine whether to provide the full key (parent.child) or just the translated key + * in the handleAPIErrors function. + */ +const keepParentChildFieldKey = ( + error: APIError, + parentFields: string[] +): boolean => { + const key = error.field?.split('.')[0]; + return parentFields.includes(key ?? ''); +}; + export const handleAPIErrors = ( errors: APIError[], setFieldError: (field: string, message: string) => void, - setError?: (message: string) => void + setError?: (message: string) => void, + parentFields?: string[] ) => { errors.forEach((error: APIError) => { if (error.field) { @@ -133,8 +148,14 @@ export const handleAPIErrors = ( * The line below gets the field name because the API returns something like this... * {"errors": [{"reason": "Invalid credit card number", "field": "data.card_number"}]} * It takes 'data.card_number' and translates it to 'card_number' + * If parentFields is provided, then it will provide the full field key for those fields without translation + * ie. In the example above, if parentFields was ['data'] then the field key would continue to be 'data.card_number'. + * This will be useful for when we want to set error messages for the nested fields of a parent. */ - const key = error.field.split('.')[error.field.split('.').length - 1]; + const key = keepParentChildFieldKey(error, parentFields ?? []) + ? error.field + : error.field.split('.')[error.field.split('.').length - 1]; + if (key) { setFieldError(key, error.reason); } From 2c59d396b23f5d8b14475a10a0f5c1b5dabe7d23 Mon Sep 17 00:00:00 2001 From: Banks Nussman <115251059+bnussman-akamai@users.noreply.github.com> Date: Thu, 2 Oct 2025 13:19:52 -0400 Subject: [PATCH 2/2] Update packages/manager/CHANGELOG.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- packages/manager/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/CHANGELOG.md b/packages/manager/CHANGELOG.md index 4ac1ca61e2c..209e79f1e83 100644 --- a/packages/manager/CHANGELOG.md +++ b/packages/manager/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [2025-10-01] - v1.151.2 +## [2025-10-02] - v1.151.2 ### Fixed: