Skip to content

Commit 16629aa

Browse files
Merge pull request #12951 from linode/staging
Release v1.151.2 - staging → master
2 parents bf5b1a8 + 2c59d39 commit 16629aa

File tree

6 files changed

+75
-6
lines changed

6 files changed

+75
-6
lines changed

packages/manager/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [2025-10-02] - v1.151.2
8+
9+
### Fixed:
10+
11+
- DBaaS - Database Create Subnet field should display backend error messages
12+
713
## [2025-09-25] - v1.151.1
814

915
### Added:

packages/manager/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "linode-manager",
33
"author": "Linode",
44
"description": "The Linode Manager website",
5-
"version": "1.151.1",
5+
"version": "1.151.2",
66
"private": true,
77
"type": "module",
88
"bugs": {

packages/manager/src/features/Databases/DatabaseCreate/DatabaseCreate.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ export const DatabaseCreate = () => {
162162
if (ipErrors) {
163163
setIPErrorsFromAPI(ipErrors);
164164
}
165-
handleAPIErrors(errors, setFieldError, setCreateError);
165+
const parentFields = ['private_network']; // List of parent fields that need the full key from the errors response
166+
handleAPIErrors(errors, setFieldError, setCreateError, parentFields);
166167
}
167168

168169
setSubmitting(false);

packages/manager/src/features/Databases/DatabaseCreate/DatabaseVPCSelector.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
BetaChip,
55
Box,
66
Checkbox,
7+
FormHelperText,
78
Notice,
89
TooltipIcon,
910
Typography,
@@ -209,6 +210,16 @@ export const DatabaseVPCSelector = (props: DatabaseVPCSelectorProps) => {
209210
'Adds a public endpoint to the database in addition to the private VPC endpoint.'
210211
}
211212
/>
213+
{errors?.private_network?.public_access && (
214+
<FormHelperText
215+
className="error-for-scroll"
216+
error
217+
role="alert"
218+
sx={{ marginTop: 0 }}
219+
>
220+
{errors?.private_network?.public_access}
221+
</FormHelperText>
222+
)}
212223
</Box>
213224
</>
214225
) : (

packages/manager/src/utilities/formikErrorUtils.test.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,17 @@ const setFieldError = vi.fn();
1717
const setError = vi.fn();
1818

1919
describe('handleAPIErrors', () => {
20-
it('should handle api error with a field', () => {
20+
it('should handle API error for a regular field', () => {
21+
const errorWithFlatField = [{ field: 'label', reason: 'Invalid label' }];
22+
handleAPIErrors(errorWithFlatField, setFieldError, setError);
23+
expect(setFieldError).toHaveBeenCalledWith(
24+
'label',
25+
errorWithFlatField[0].reason
26+
);
27+
expect(setError).not.toHaveBeenCalled();
28+
});
29+
30+
it('should handle API error for a parent field when parentFields is not provided', () => {
2131
handleAPIErrors(errorWithField, setFieldError, setError);
2232
expect(setFieldError).toHaveBeenCalledWith(
2333
'card_number',
@@ -26,7 +36,27 @@ describe('handleAPIErrors', () => {
2636
expect(setError).not.toHaveBeenCalled();
2737
});
2838

29-
it('should handle a general api error', () => {
39+
it('should handle API error for a parent field when parentFields is provided', () => {
40+
const errorWithParentField = [
41+
{ field: 'private_network.subnet_id', reason: 'Invalid subnet ID' },
42+
];
43+
44+
const parentFields = ['private_network']; // Provide parentFields so full field key is used
45+
46+
handleAPIErrors(
47+
errorWithParentField,
48+
setFieldError,
49+
setError,
50+
parentFields
51+
);
52+
expect(setFieldError).toHaveBeenCalledWith(
53+
'private_network.subnet_id',
54+
errorWithParentField[0].reason
55+
);
56+
expect(setError).not.toHaveBeenCalled();
57+
});
58+
59+
it('should handle a general API error', () => {
3060
handleAPIErrors(errorWithoutField, setFieldError, setError);
3161
expect(setFieldError).not.toHaveBeenCalledWith();
3262
expect(setError).toHaveBeenCalledWith(errorWithoutField[0].reason);

packages/manager/src/utilities/formikErrorUtils.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,19 +122,40 @@ export const handleGeneralErrors = (
122122
}
123123
};
124124

125+
/**
126+
* This function checks if the parent field from the APIError object is included
127+
* in parentFields list and returns true if if it's found.
128+
* This check will determine whether to provide the full key (parent.child) or just the translated key
129+
* in the handleAPIErrors function.
130+
*/
131+
const keepParentChildFieldKey = (
132+
error: APIError,
133+
parentFields: string[]
134+
): boolean => {
135+
const key = error.field?.split('.')[0];
136+
return parentFields.includes(key ?? '');
137+
};
138+
125139
export const handleAPIErrors = (
126140
errors: APIError[],
127141
setFieldError: (field: string, message: string) => void,
128-
setError?: (message: string) => void
142+
setError?: (message: string) => void,
143+
parentFields?: string[]
129144
) => {
130145
errors.forEach((error: APIError) => {
131146
if (error.field) {
132147
/**
133148
* The line below gets the field name because the API returns something like this...
134149
* {"errors": [{"reason": "Invalid credit card number", "field": "data.card_number"}]}
135150
* It takes 'data.card_number' and translates it to 'card_number'
151+
* If parentFields is provided, then it will provide the full field key for those fields without translation
152+
* ie. In the example above, if parentFields was ['data'] then the field key would continue to be 'data.card_number'.
153+
* This will be useful for when we want to set error messages for the nested fields of a parent.
136154
*/
137-
const key = error.field.split('.')[error.field.split('.').length - 1];
155+
const key = keepParentChildFieldKey(error, parentFields ?? [])
156+
? error.field
157+
: error.field.split('.')[error.field.split('.').length - 1];
158+
138159
if (key) {
139160
setFieldError(key, error.reason);
140161
}

0 commit comments

Comments
 (0)