Provisioning: Show field errors for sync interval (#111925)

This commit is contained in:
Alex Khomenko 2025-10-03 02:23:36 +03:00 committed by GitHub
parent 13d9829836
commit 5798181fb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 2 deletions

View File

@ -12,7 +12,12 @@ import { getGitProviderFields } from './fields';
import { WizardFormData } from './types';
export const FinishStep = memo(function FinishStep() {
const { register, watch, setValue } = useFormContext<WizardFormData>();
const {
register,
watch,
setValue,
formState: { errors },
} = useFormContext<WizardFormData>();
const settings = useGetFrontendSettingsQuery();
const [type, readOnly] = watch(['repository.type', 'repository.readOnly']);
@ -42,6 +47,8 @@ export const FinishStep = memo(function FinishStep() {
'How often to sync changes from the repository'
)}
required
error={errors?.repository?.sync?.intervalSeconds?.message}
invalid={!!errors?.repository?.sync?.intervalSeconds?.message}
>
<Input
{...register('repository.sync.intervalSeconds', {

View File

@ -3,7 +3,7 @@ import { ErrorDetails } from 'app/api/clients/provisioning/v0alpha1';
import { WizardFormData } from '../Wizard/types';
export type RepositoryField = keyof WizardFormData['repository'];
export type RepositoryFormPath = `repository.${RepositoryField}`;
export type RepositoryFormPath = `repository.${RepositoryField}` | `repository.sync.intervalSeconds`;
export type FormErrorTuple = [RepositoryFormPath | null, { message: string } | null];
/**
@ -25,7 +25,13 @@ export const getFormErrors = (errors: ErrorDetails[]): FormErrorTuple => {
'bitbucket.url',
'git.branch',
'git.url',
'sync.intervalSeconds',
];
const nestedFieldMap: Record<string, RepositoryFormPath> = {
'sync.intervalSeconds': 'repository.sync.intervalSeconds',
};
const fieldMap: Record<string, RepositoryFormPath> = {
path: 'repository.path',
branch: 'repository.branch',
@ -37,6 +43,12 @@ export const getFormErrors = (errors: ErrorDetails[]): FormErrorTuple => {
if (error.field) {
const cleanField = error.field.replace('spec.', '');
if (fieldsToValidate.includes(cleanField)) {
// 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
const fieldParts = cleanField.split('.');
const lastPart = fieldParts[fieldParts.length - 1];