From 1cdd3fdfe218e873b298858b6838f553ba918e6b Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Wed, 21 Feb 2024 10:43:28 +1300 Subject: [PATCH] fix(input): allow clearing number inputs [EE-6714] (#11187) --- app/react-tools/yup-schemas.ts | 19 +++++++++++++++++++ .../form-components/Input/Input.tsx | 4 ++++ .../Slider/SliderWithInput.tsx | 6 ++---- .../ResourcesTab/ResourcesFieldset.tsx | 9 +++++---- .../columns/schedulingMode/ScaleForm.tsx | 7 ++++++- .../kubeServicesValidation.ts | 8 ++++---- .../AutoScalingFormSection.tsx | 6 +++--- .../ReplicationFormSection.tsx | 12 ++++++------ .../replicationValidation.ts | 6 ++++-- .../resourceReservationValidation.ts | 5 +++-- .../KubeSettingsPanel/validation.ts | 7 ++++--- 11 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 app/react-tools/yup-schemas.ts diff --git a/app/react-tools/yup-schemas.ts b/app/react-tools/yup-schemas.ts new file mode 100644 index 000000000..4f614e21d --- /dev/null +++ b/app/react-tools/yup-schemas.ts @@ -0,0 +1,19 @@ +import { NumberSchema, number } from 'yup'; + +/** + * Returns a Yup schema for a number that can also be NaN. + * + * This function is a workaround for a known issue in Yup where it throws type errors + * when the number input is empty, having a value NaN. Yup doesn't like NaN values. + * More details can be found in these GitHub issues: + * https://github.com/jquense/yup/issues/1330 + * https://github.com/jquense/yup/issues/211 + * + * @param errorMessage The custom error message to display when the value is required. + * @returns A Yup number schema with a custom type error message. + */ +export function nanNumberSchema( + errorMessage = 'Value is required' +): NumberSchema { + return number().typeError(errorMessage); +} diff --git a/app/react/components/form-components/Input/Input.tsx b/app/react/components/form-components/Input/Input.tsx index 2108b314a..1bd02e01f 100644 --- a/app/react/components/form-components/Input/Input.tsx +++ b/app/react/components/form-components/Input/Input.tsx @@ -12,6 +12,8 @@ export const InputWithRef = forwardRef< export function Input({ className, mRef: ref, + value, + type, ...props }: InputHTMLAttributes & { mRef?: Ref; @@ -20,6 +22,8 @@ export function Input({ diff --git a/app/react/components/form-components/Slider/SliderWithInput.tsx b/app/react/components/form-components/Slider/SliderWithInput.tsx index bfbff328f..c66d9725b 100644 --- a/app/react/components/form-components/Slider/SliderWithInput.tsx +++ b/app/react/components/form-components/Slider/SliderWithInput.tsx @@ -20,7 +20,7 @@ export function SliderWithInput({ visibleTooltip?: boolean; }) { return ( -
+
{max && (
- onChange(Number.isNaN(value) ? 0 : value) - } + onChange={(e) => onChange(e.target.valueAsNumber)} className="w-32" data-cy={`${dataCy}Input`} /> diff --git a/app/react/docker/containers/CreateView/ResourcesTab/ResourcesFieldset.tsx b/app/react/docker/containers/CreateView/ResourcesTab/ResourcesFieldset.tsx index aace001ef..e2bc40ddc 100644 --- a/app/react/docker/containers/CreateView/ResourcesTab/ResourcesFieldset.tsx +++ b/app/react/docker/containers/CreateView/ResourcesTab/ResourcesFieldset.tsx @@ -1,8 +1,9 @@ import { FormikErrors } from 'formik'; -import { number, object, SchemaOf } from 'yup'; +import { object, SchemaOf } from 'yup'; import { useSystemLimits } from '@/react/docker/proxy/queries/useInfo'; import { useEnvironmentId } from '@/react/hooks/useEnvironmentId'; +import { nanNumberSchema } from '@/react-tools/yup-schemas'; import { FormControl } from '@@/form-components/FormControl'; import { FormSection } from '@@/form-components/FormSection'; @@ -94,15 +95,15 @@ export function resourcesValidation({ maxCpu?: number; } = {}): SchemaOf { return object({ - reservation: number() + reservation: nanNumberSchema() .min(0) .max(maxMemory, `Value must be between 0 and ${maxMemory}`) .default(0), - limit: number() + limit: nanNumberSchema() .min(0) .max(maxMemory, `Value must be between 0 and ${maxMemory}`) .default(0), - cpu: number() + cpu: nanNumberSchema() .min(0) .max(maxCpu, `Value must be between 0 and ${maxCpu}`) .default(0), diff --git a/app/react/docker/services/ListView/ServicesDatatable/columns/schedulingMode/ScaleForm.tsx b/app/react/docker/services/ListView/ServicesDatatable/columns/schedulingMode/ScaleForm.tsx index 8cafed392..716903838 100644 --- a/app/react/docker/services/ListView/ServicesDatatable/columns/schedulingMode/ScaleForm.tsx +++ b/app/react/docker/services/ListView/ServicesDatatable/columns/schedulingMode/ScaleForm.tsx @@ -32,7 +32,7 @@ export function ScaleForm({ type="number" min={0} step={1} - value={values.replicas} + value={Number.isNaN(values.replicas) ? '' : values.replicas} onKeyUp={(event) => { if (event.key === 'Escape') { onClose(); @@ -48,6 +48,11 @@ export function ScaleForm({