Wizard: Add step validation to Locale
This adds step validation to Locale, allowing to properly validate imported values.
This commit is contained in:
parent
52c790bb4a
commit
62bbf6d688
4 changed files with 83 additions and 2 deletions
|
|
@ -47,6 +47,7 @@ import {
|
|||
useTimezoneValidation,
|
||||
useFirewallValidation,
|
||||
useServicesValidation,
|
||||
useLocaleValidation,
|
||||
} from './utilities/useValidation';
|
||||
import {
|
||||
isAwsAccountIdValid,
|
||||
|
|
@ -225,6 +226,8 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
|
|||
const fileSystemValidation = useFilesystemValidation();
|
||||
// Timezone
|
||||
const timezoneValidation = useTimezoneValidation();
|
||||
// Locale
|
||||
const localeValidation = useLocaleValidation();
|
||||
// Hostname
|
||||
const hostnameValidation = useHostnameValidation();
|
||||
// Kernel
|
||||
|
|
@ -506,8 +509,12 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
|
|||
key="wizard-locale"
|
||||
navItem={customStatusNavItem}
|
||||
isHidden={!isLocaleEnabled}
|
||||
status={localeValidation.disabledNext ? 'error' : 'default'}
|
||||
footer={
|
||||
<CustomWizardFooter disableNext={false} optional={true} />
|
||||
<CustomWizardFooter
|
||||
disableNext={localeValidation.disabledNext}
|
||||
optional={true}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<LocaleStep />
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import React, { useEffect, useState } from 'react';
|
|||
import {
|
||||
Button,
|
||||
FormGroup,
|
||||
HelperText,
|
||||
HelperTextItem,
|
||||
MenuToggle,
|
||||
MenuToggleElement,
|
||||
Select,
|
||||
|
|
@ -20,12 +22,16 @@ import {
|
|||
selectKeyboard,
|
||||
} from '../../../../../store/wizardSlice';
|
||||
import sortfn from '../../../../../Utilities/sortfn';
|
||||
import { useLocaleValidation } from '../../../utilities/useValidation';
|
||||
import { keyboardsList } from '../keyboardsList';
|
||||
|
||||
const KeyboardDropDown = () => {
|
||||
const keyboard = useAppSelector(selectKeyboard);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const stepValidation = useLocaleValidation();
|
||||
|
||||
const [errorText, setErrorText] = useState(stepValidation.errors['keyboard']);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [inputValue, setInputValue] = useState<string>('');
|
||||
const [filterValue, setFilterValue] = useState<string>('');
|
||||
|
|
@ -70,6 +76,7 @@ const KeyboardDropDown = () => {
|
|||
if (value && !value.includes('No results')) {
|
||||
setInputValue(value);
|
||||
setFilterValue('');
|
||||
setErrorText('');
|
||||
dispatch(changeKeyboard(value));
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
|
@ -91,6 +98,7 @@ const KeyboardDropDown = () => {
|
|||
const onClearButtonClick = () => {
|
||||
setInputValue('');
|
||||
setFilterValue('');
|
||||
setErrorText('');
|
||||
dispatch(changeKeyboard(''));
|
||||
};
|
||||
|
||||
|
|
@ -146,6 +154,11 @@ const KeyboardDropDown = () => {
|
|||
))}
|
||||
</SelectList>
|
||||
</Select>
|
||||
{errorText && (
|
||||
<HelperText>
|
||||
<HelperTextItem variant={'error'}>{errorText}</HelperTextItem>
|
||||
</HelperText>
|
||||
)}
|
||||
</FormGroup>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {
|
|||
Chip,
|
||||
ChipGroup,
|
||||
FormGroup,
|
||||
HelperText,
|
||||
HelperTextItem,
|
||||
MenuToggle,
|
||||
MenuToggleElement,
|
||||
Select,
|
||||
|
|
@ -23,12 +25,18 @@ import {
|
|||
selectLanguages,
|
||||
} from '../../../../../store/wizardSlice';
|
||||
import sortfn from '../../../../../Utilities/sortfn';
|
||||
import { useLocaleValidation } from '../../../utilities/useValidation';
|
||||
import { languagesList } from '../languagesList';
|
||||
|
||||
const LanguagesDropDown = () => {
|
||||
const languages = useAppSelector(selectLanguages);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const stepValidation = useLocaleValidation();
|
||||
const unknownLanguages = stepValidation.errors['languages']
|
||||
? stepValidation.errors['languages'].split(' ')
|
||||
: [];
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [inputValue, setInputValue] = useState<string>('');
|
||||
const [filterValue, setFilterValue] = useState<string>('');
|
||||
|
|
@ -92,6 +100,13 @@ const LanguagesDropDown = () => {
|
|||
setFilterValue('');
|
||||
};
|
||||
|
||||
const handleRemoveLang = (_event: React.MouseEvent, value: string) => {
|
||||
dispatch(removeLanguage(value));
|
||||
if (unknownLanguages.length > 0) {
|
||||
unknownLanguages.filter((lang) => lang !== value);
|
||||
}
|
||||
};
|
||||
|
||||
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
|
||||
<MenuToggle
|
||||
ref={toggleRef}
|
||||
|
|
@ -143,9 +158,18 @@ const LanguagesDropDown = () => {
|
|||
))}
|
||||
</SelectList>
|
||||
</Select>
|
||||
{unknownLanguages.length > 0 && (
|
||||
<HelperText>
|
||||
<HelperTextItem
|
||||
variant={'error'}
|
||||
>{`Unknown languages: ${unknownLanguages.join(
|
||||
', '
|
||||
)}`}</HelperTextItem>
|
||||
</HelperText>
|
||||
)}
|
||||
<ChipGroup numChips={5} className="pf-v5-u-mt-sm pf-v5-u-w-100">
|
||||
{languages?.map((lang) => (
|
||||
<Chip key={lang} onClick={() => dispatch(removeLanguage(lang))}>
|
||||
<Chip key={lang} onClick={(e) => handleRemoveLang(e, lang)}>
|
||||
{lang}
|
||||
</Chip>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,11 @@ import {
|
|||
selectNtpServers,
|
||||
selectFirewall,
|
||||
selectServices,
|
||||
selectLanguages,
|
||||
selectKeyboard,
|
||||
} from '../../../store/wizardSlice';
|
||||
import { keyboardsList } from '../steps/Locale/keyboardsList';
|
||||
import { languagesList } from '../steps/Locale/languagesList';
|
||||
import {
|
||||
getDuplicateMountPoints,
|
||||
isBlueprintNameValid,
|
||||
|
|
@ -57,6 +61,7 @@ export function useIsBlueprintValid(): boolean {
|
|||
const filesystem = useFilesystemValidation();
|
||||
const snapshot = useSnapshotValidation();
|
||||
const timezone = useTimezoneValidation();
|
||||
const locale = useLocaleValidation();
|
||||
const hostname = useHostnameValidation();
|
||||
const kernel = useKernelValidation();
|
||||
const firewall = useFirewallValidation();
|
||||
|
|
@ -68,6 +73,7 @@ export function useIsBlueprintValid(): boolean {
|
|||
!filesystem.disabledNext &&
|
||||
!snapshot.disabledNext &&
|
||||
!timezone.disabledNext &&
|
||||
!locale.disabledNext &&
|
||||
!hostname.disabledNext &&
|
||||
!kernel.disabledNext &&
|
||||
!firewall.disabledNext &&
|
||||
|
|
@ -179,6 +185,37 @@ export function useTimezoneValidation(): StepValidation {
|
|||
return { errors: {}, disabledNext: false };
|
||||
}
|
||||
|
||||
export function useLocaleValidation(): StepValidation {
|
||||
const languages = useAppSelector(selectLanguages);
|
||||
const keyboard = useAppSelector(selectKeyboard);
|
||||
|
||||
const errors = {};
|
||||
const unknownLanguages = [];
|
||||
|
||||
if (languages && languages.length > 0) {
|
||||
for (const lang of languages) {
|
||||
if (!languagesList.includes(lang)) {
|
||||
unknownLanguages.push(lang);
|
||||
}
|
||||
}
|
||||
|
||||
if (unknownLanguages.length > 0) {
|
||||
Object.assign(errors, {
|
||||
languages: unknownLanguages.join(' '),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboard && !keyboardsList.includes(keyboard)) {
|
||||
Object.assign(errors, { keyboard: 'Unknown keyboard' });
|
||||
}
|
||||
|
||||
return {
|
||||
errors,
|
||||
disabledNext: unknownLanguages.length > 0 || 'keyboard' in errors,
|
||||
};
|
||||
}
|
||||
|
||||
export function useFirstBootValidation(): StepValidation {
|
||||
const script = useAppSelector(selectFirstBootScript);
|
||||
let hasShebang = false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue