Wizard: Refactor hostname and blueprint name inputs

This commit Implement refactor of HookValidatedInput for hostname and blueprint name
fields, addressing the following bugs:

1) Fixes a bug where the validation symbol persisted after a user deleted the value in the hostname field.
2) Fixes a bug where the validation symbol persisted after a user deleted the value in the blueprint name field.

These changes improve code maintainability and provide a more consistent user experience.
This commit is contained in:
Michal Gold 2025-02-10 16:03:27 +02:00 committed by Lucas Garfield
parent 1d39a57391
commit 12aa5cdf52
4 changed files with 29 additions and 17 deletions

View file

@ -50,6 +50,7 @@ type ValidationInputProp = TextInputProps &
event: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
value: string
) => void;
isRequired?: boolean;
};
type ErrorMessageProps = {
@ -117,12 +118,13 @@ export const ValidatedInputAndTextArea = ({
onChange,
ariaLabel,
inputType = 'textInput',
isRequired,
}: ValidationInputProp) => {
const errorMessage = stepValidation.errors[fieldName];
const hasError = errorMessage !== '';
const [isPristine, setIsPristine] = useState(!value);
const validated = getValidationState(isPristine, errorMessage);
const validated = getValidationState(isPristine, errorMessage, isRequired);
const handleBlur = () => {
if (value) {
@ -164,9 +166,14 @@ export const ValidatedInputAndTextArea = ({
const getValidationState = (
isPristine: boolean,
errorMessage: string
errorMessage: string,
isRequired: boolean | undefined
): ValidationResult => {
const validated = isPristine ? 'default' : errorMessage ? 'error' : 'success';
const validated = isPristine
? 'default'
: (isRequired && errorMessage) || errorMessage
? 'error'
: 'success';
return validated;
};

View file

@ -19,7 +19,10 @@ import {
} from '../../../../store/wizardSlice';
import { useGenerateDefaultName } from '../../utilities/useGenerateDefaultName';
import { useDetailsValidation } from '../../utilities/useValidation';
import { HookValidatedInput } from '../../ValidatedInput';
import {
HookValidatedInput,
ValidatedInputAndTextArea,
} from '../../ValidatedInput';
const DetailsStep = () => {
const dispatch = useAppDispatch();
@ -55,15 +58,15 @@ const DetailsStep = () => {
blueprint.
</Text>
<FormGroup isRequired label="Blueprint name" fieldId="blueprint-name">
<HookValidatedInput
<ValidatedInputAndTextArea
ariaLabel="blueprint name"
dataTestId="blueprint"
value={blueprintName}
isDisabled={false}
onChange={handleNameChange}
placeholder="Add blueprint name"
stepValidation={stepValidation}
fieldName="name"
isRequired={true}
/>
<FormHelperText>
<HelperText>

View file

@ -8,7 +8,7 @@ import {
selectHostname,
} from '../../../../../store/wizardSlice';
import { useHostnameValidation } from '../../../utilities/useValidation';
import { HookValidatedInput } from '../../../ValidatedInput';
import { ValidatedInputAndTextArea } from '../../../ValidatedInput';
const HostnameInput = () => {
const dispatch = useAppDispatch();
@ -22,7 +22,7 @@ const HostnameInput = () => {
return (
<FormGroup label="Hostname">
<HookValidatedInput
<ValidatedInputAndTextArea
ariaLabel="hostname input"
value={hostname}
onChange={handleChange}

View file

@ -250,15 +250,14 @@ export function useHostnameValidation(): StepValidation {
const errorMessage =
'Invalid hostname. The hostname should be composed of up to 64 7-bit ASCII lower-case alphanumeric characters or hyphens forming a valid DNS domain name. It is recommended that this name contains only a single label, i.e. without any dots.';
if (!isHostnameValid(hostname)) {
return {
errors: {
hostname: errorMessage,
},
disabledNext: true,
};
}
return { errors: {}, disabledNext: false };
const hostnameError = !isHostnameValid(hostname) ? errorMessage : '';
return {
errors: {
hostname: hostnameError,
},
disabledNext: !!hostnameError,
};
}
export function useKernelValidation(): StepValidation {
@ -479,6 +478,9 @@ export function useDetailsValidation(): StepValidation {
}, [blueprintId, name, setUniqueName, trigger, nameValid]);
let nameError = '';
if (!name) {
nameError = 'Blueprint name is required';
}
if (name && !nameValid) {
nameError = 'Invalid blueprint name';
} else if (uniqueName === false) {