2025-06-13 18:24:37 +08:00
|
|
|
import { ErrorDetails } from 'app/api/clients/provisioning/v0alpha1';
|
2025-04-11 21:26:42 +08:00
|
|
|
|
|
|
|
|
import { WizardFormData } from '../Wizard/types';
|
|
|
|
|
|
|
|
|
|
export type RepositoryField = keyof WizardFormData['repository'];
|
2025-10-02 14:54:41 +08:00
|
|
|
export type RepositoryFormPath = `repository.${RepositoryField}` | `repository.sync.intervalSeconds`;
|
2025-04-11 21:26:42 +08:00
|
|
|
export type FormErrorTuple = [RepositoryFormPath | null, { message: string } | null];
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Maps API error details to form error fields for React Hook Form
|
|
|
|
|
*
|
|
|
|
|
* @param errors Array of error details from the API response
|
|
|
|
|
* @returns Tuple with form field path and error message
|
|
|
|
|
*/
|
|
|
|
|
export const getFormErrors = (errors: ErrorDetails[]): FormErrorTuple => {
|
2025-07-21 13:29:41 +08:00
|
|
|
const fieldsToValidate = [
|
|
|
|
|
'local.path',
|
|
|
|
|
'github.branch',
|
|
|
|
|
'github.url',
|
2025-09-25 23:10:13 +08:00
|
|
|
'github.path',
|
2025-08-23 00:38:28 +08:00
|
|
|
'secure.token',
|
2025-07-21 13:29:41 +08:00
|
|
|
'gitlab.branch',
|
|
|
|
|
'gitlab.url',
|
|
|
|
|
'bitbucket.branch',
|
|
|
|
|
'bitbucket.url',
|
|
|
|
|
'git.branch',
|
|
|
|
|
'git.url',
|
2025-10-02 14:54:41 +08:00
|
|
|
'sync.intervalSeconds',
|
2025-07-21 13:29:41 +08:00
|
|
|
];
|
2025-10-02 14:54:41 +08:00
|
|
|
|
|
|
|
|
const nestedFieldMap: Record<string, RepositoryFormPath> = {
|
|
|
|
|
'sync.intervalSeconds': 'repository.sync.intervalSeconds',
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-11 21:26:42 +08:00
|
|
|
const fieldMap: Record<string, RepositoryFormPath> = {
|
|
|
|
|
path: 'repository.path',
|
|
|
|
|
branch: 'repository.branch',
|
|
|
|
|
url: 'repository.url',
|
|
|
|
|
token: 'repository.token',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (const error of errors) {
|
|
|
|
|
if (error.field) {
|
|
|
|
|
const cleanField = error.field.replace('spec.', '');
|
|
|
|
|
if (fieldsToValidate.includes(cleanField)) {
|
2025-10-02 14:54:41 +08:00
|
|
|
// Check for direct nested field mapping first
|
|
|
|
|
if (cleanField in nestedFieldMap) {
|
|
|
|
|
return [nestedFieldMap[cleanField], { message: error.detail || `Invalid ${cleanField}` }];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fall back to simple field mapping for non-nested fields
|
2025-04-11 21:26:42 +08:00
|
|
|
const fieldParts = cleanField.split('.');
|
|
|
|
|
const lastPart = fieldParts[fieldParts.length - 1];
|
|
|
|
|
|
|
|
|
|
if (lastPart in fieldMap) {
|
|
|
|
|
return [fieldMap[lastPart], { message: error.detail || `Invalid ${lastPart}` }];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [null, null];
|
|
|
|
|
};
|