Wizard: Validate snapshot date with useValidation

This commit is contained in:
Ondrej Ezr 2024-07-31 18:00:49 +02:00 committed by Klara Simickova
parent 312f3d6968
commit 2cf95bea02
4 changed files with 44 additions and 21 deletions

View file

@ -29,6 +29,7 @@ import Azure from './steps/TargetEnvironment/Azure';
import Gcp from './steps/TargetEnvironment/Gcp';
import {
useFilesystemValidation,
useSnapshotValidation,
useFirstBootValidation,
useDetailsValidation,
} from './utilities/useValidation';
@ -60,8 +61,6 @@ import {
selectGcpShareMethod,
selectImageTypes,
addImageType,
selectSnapshotDate,
selectUseLatest,
selectRegistrationType,
selectActivationKey,
} from '../../store/wizardSlice';
@ -181,9 +180,7 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
const registrationType = useAppSelector(selectRegistrationType);
const activationKey = useAppSelector(selectActivationKey);
// Snapshots
const snapshotDate = useAppSelector(selectSnapshotDate);
const useLatest = useAppSelector(selectUseLatest);
const snapshotStepRequiresChoice = !useLatest && !snapshotDate;
const snapshotValidation = useSnapshotValidation();
// Filesystem
const [filesystemPristine, setFilesystemPristine] = useState(true);
const fileSystemValidation = useFilesystemValidation();
@ -372,10 +369,12 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
name="Repository snapshot"
id="wizard-repository-snapshot"
key="wizard-repository-snapshot"
navItem={customStatusNavItem}
status={snapshotValidation.disabledNext ? 'error' : 'default'}
isHidden={!snapshottingEnabled}
footer={
<CustomWizardFooter
disableNext={snapshotStepRequiresChoice}
disableNext={snapshotValidation.disabledNext}
/>
}
>
@ -385,7 +384,7 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
name="Custom repositories"
id="wizard-custom-repositories"
key="wizard-custom-repositories"
isDisabled={snapshotStepRequiresChoice}
isDisabled={snapshotValidation.disabledNext}
footer={<CustomWizardFooter disableNext={false} />}
>
<RepositoriesStep />
@ -394,7 +393,7 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
name="Additional packages"
id="wizard-additional-packages"
key="wizard-additional-packages"
isDisabled={snapshotStepRequiresChoice}
isDisabled={snapshotValidation.disabledNext}
footer={<CustomWizardFooter disableNext={false} />}
>
<PackagesStep />
@ -419,7 +418,6 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
<WizardStep
name="Details"
id={'step-details'}
isDisabled={snapshotStepRequiresChoice}
navItem={customStatusNavItem}
status={detailsValidation.disabledNext ? 'error' : 'default'}
footer={
@ -433,7 +431,6 @@ const CreateImageWizard = ({ isEdit }: CreateImageWizardProps) => {
<WizardStep
name="Review"
id="step-review"
isDisabled={snapshotStepRequiresChoice}
footer={<ReviewWizardFooter />}
>
{/* Intentional prop drilling for simplicity - To be removed */}

View file

@ -22,15 +22,7 @@ import {
dateToMMDDYYYY,
parseMMDDYYYYtoDate,
} from '../../../../Utilities/time';
const dateValidators = [
(date: Date) => {
if (date.getTime() > Date.now()) {
return 'Cannot set a date in the future';
}
return '';
},
];
import { isSnapshotDateValid } from '../../validators';
export default function Snapshot() {
const dispatch = useAppDispatch();
@ -89,7 +81,14 @@ export default function Snapshot() {
placeholder="MM/DD/YYYY"
dateParse={parseMMDDYYYYtoDate}
dateFormat={dateToMMDDYYYY}
validators={dateValidators}
validators={[
(date: Date) => {
if (!isSnapshotDateValid(date)) {
return 'Cannot set a date in the future';
}
return '';
},
]}
onChange={(_, val) => dispatch(changeSnapshotDate(val))}
/>
<Button

View file

@ -13,12 +13,15 @@ import {
selectFileSystemConfigurationType,
selectFirstBootScript,
selectPartitions,
selectSnapshotDate,
selectUseLatest,
} from '../../../store/wizardSlice';
import {
getDuplicateMountPoints,
isBlueprintNameValid,
isBlueprintDescriptionValid,
isMountpointMinSizeValid,
isSnapshotValid,
} from '../validators';
export type StepValidation = {
@ -30,10 +33,14 @@ export type StepValidation = {
export function useIsBlueprintValid(): boolean {
const filesystem = useFilesystemValidation();
const snapshot = useSnapshotValidation();
const firstBoot = useFirstBootValidation();
const details = useDetailsValidation();
return (
!filesystem.disabledNext && !firstBoot.disabledNext && !details.disabledNext
!filesystem.disabledNext &&
!snapshot.disabledNext &&
!firstBoot.disabledNext &&
!details.disabledNext
);
}
@ -61,6 +68,19 @@ export function useFilesystemValidation(): StepValidation {
return { errors, disabledNext };
}
export function useSnapshotValidation(): StepValidation {
const snapshotDate = useAppSelector(selectSnapshotDate);
const useLatest = useAppSelector(selectUseLatest);
if (!useLatest && !isSnapshotValid(snapshotDate)) {
return {
errors: { snapshotDate: 'Invalid snapshot date' },
disabledNext: true,
};
}
return { errors: {}, disabledNext: false };
}
export function useFirstBootValidation(): StepValidation {
const script = useAppSelector(selectFirstBootScript);
let hasShebang = false;

View file

@ -51,6 +51,13 @@ export const isBlueprintNameValid = (blueprintName: string) =>
blueprintName.length <= 100 &&
/\w+/.test(blueprintName);
export const isSnapshotDateValid = (date: Date) => date.getTime() <= Date.now();
export const isSnapshotValid = (dateString: string) => {
const date = new Date(dateString);
return !isNaN(date.getTime()) && isSnapshotDateValid(date);
};
export const isBlueprintDescriptionValid = (blueprintDescription: string) => {
return blueprintDescription.length <= 250;
};