From 63eda4adc95c3c82f577d1e33113bbe4422dbfe6 Mon Sep 17 00:00:00 2001
From: Samir Kamal <1954121+skamril@users.noreply.github.com>
Date: Thu, 16 May 2024 12:39:13 +0200
Subject: [PATCH 1/3] feat(ui-utils): add overload signatures for
`validateNumber` function in validationUtils
---
webapp/src/utils/validationUtils.ts | 44 ++++++++++++++++++++++++-----
1 file changed, 37 insertions(+), 7 deletions(-)
diff --git a/webapp/src/utils/validationUtils.ts b/webapp/src/utils/validationUtils.ts
index 5b3f60091d..5760f285ae 100644
--- a/webapp/src/utils/validationUtils.ts
+++ b/webapp/src/utils/validationUtils.ts
@@ -4,6 +4,11 @@ import { t } from "i18next";
// Types
////////////////////////////////////////////////////////////////
+interface NumberValidationOptions {
+ min?: number;
+ max?: number;
+}
+
interface ValidationOptions {
existingValues?: string[];
excludedValues?: string[];
@@ -153,22 +158,47 @@ export function validatePassword(password: string): string | true {
/**
* Validates a number against specified numerical limits.
*
+ * @example
+ * validateNumber(5, { min: 0, max: 10 }); // true
+ * validateNumber(9, { min: 10, max: 20 }); // Error message
+ *
+ *
+ * @example
With currying.
+ * const fn = validateNumber({ min: 0, max: 10 });
+ * fn(5); // true
+ * fn(11); // Error message
+ *
* @param value - The number to validate.
- * @param options - Configuration options for validation including min and max values. (Optional)
- * @param [options.min=Number.MIN_SAFE_INTEGER] - Minimum allowed value for the number.
- * @param [options.max=Number.MAX_SAFE_INTEGER] - Maximum allowed value for the number.
+ * @param [options] - Configuration options for validation.
+ * @param [options.min=Number.MIN_SAFE_INTEGER] - Minimum allowed value.
+ * @param [options.max=Number.MAX_SAFE_INTEGER] - Maximum allowed value.
* @returns True if validation is successful, or a localized error message if it fails.
*/
export function validateNumber(
value: number,
- options?: ValidationOptions,
-): string | true {
- if (typeof value !== "number" || isNaN(value) || !isFinite(value)) {
+ options?: NumberValidationOptions,
+): string | true;
+
+export function validateNumber(
+ options?: NumberValidationOptions,
+): (value: number) => string | true;
+
+export function validateNumber(
+ valueOrOpts?: number | NumberValidationOptions,
+ options: NumberValidationOptions = {},
+): (string | true) | ((value: number) => string | true) {
+ if (typeof valueOrOpts !== "number") {
+ return (v: number) => validateNumber(v, valueOrOpts);
+ }
+
+ const value = valueOrOpts;
+
+ if (!isFinite(value)) {
return t("form.field.invalidNumber", { value });
}
const { min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER } =
- options || {};
+ options;
if (value < min) {
return t("form.field.minValue", { 0: min });
From 430d88bad3f488162fc08a298195a9d20c6d4e2c Mon Sep 17 00:00:00 2001
From: Samir Kamal <1954121+skamril@users.noreply.github.com>
Date: Wed, 15 May 2024 14:07:19 +0200
Subject: [PATCH 2/3] style(ui-thermals): use curry version of `validateNumber`
---
.../Modelization/Areas/Thermal/Fields.tsx | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx
index 15f67cdb41..b553152ab8 100644
--- a/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Modelization/Areas/Thermal/Fields.tsx
@@ -74,7 +74,7 @@ function Fields() {
name="unitCount"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 1 }),
+ validate: validateNumber({ min: 1 }),
setValueAs: Math.floor,
}}
/>
@@ -83,7 +83,7 @@ function Fields() {
name="nominalCapacity"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
validateNumber(v, { min: 0, max: 100 }),
+ validate: validateNumber({ min: 0, max: 100 }),
}}
/>
validateNumber(v, { min: 1, max: 168 }),
+ validate: validateNumber({ min: 1, max: 168 }),
setValueAs: Math.floor,
}}
/>
@@ -113,7 +113,7 @@ function Fields() {
name="minDownTime"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 1, max: 168 }),
+ validate: validateNumber({ min: 1, max: 168 }),
setValueAs: Math.floor,
}}
/>
@@ -134,7 +134,7 @@ function Fields() {
name="efficiency"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
disabled={!isTSCost}
/>
@@ -143,7 +143,7 @@ function Fields() {
name="marginalCost"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
@@ -152,7 +152,7 @@ function Fields() {
name="startupCost"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
disabled={!isTSCost}
/>
@@ -196,7 +196,7 @@ function Fields() {
name={name}
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0 }),
+ validate: validateNumber({ min: 0 }),
}}
/>
),
@@ -218,7 +218,7 @@ function Fields() {
name="volatilityForced"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0, max: 1 }),
+ validate: validateNumber({ min: 0, max: 1 }),
}}
inputProps={{ step: 0.1 }}
/>
@@ -227,7 +227,7 @@ function Fields() {
name="volatilityPlanned"
control={control}
rules={{
- validate: (v) => validateNumber(v, { min: 0, max: 1 }),
+ validate: validateNumber({ min: 0, max: 1 }),
}}
inputProps={{ step: 0.1 }}
/>
From 6afb77cfd697b901073e0fc979a52cd50e22e05b Mon Sep 17 00:00:00 2001
From: Samir Kamal <1954121+skamril@users.noreply.github.com>
Date: Thu, 16 May 2024 12:18:17 +0200
Subject: [PATCH 3/3] fix(ui-utils): change error message for string length in
validationUtils
---
webapp/public/locales/en/main.json | 3 +-
webapp/public/locales/fr/main.json | 3 +-
.../BindingConstraints/AddDialog.tsx | 2 +-
.../BindingConstView/ConstraintFields.tsx | 2 +-
webapp/src/utils/validationUtils.ts | 28 +++++++++----------
5 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/webapp/public/locales/en/main.json b/webapp/public/locales/en/main.json
index 49ed4ce172..ccfac647f2 100644
--- a/webapp/public/locales/en/main.json
+++ b/webapp/public/locales/en/main.json
@@ -123,7 +123,8 @@
"form.asyncDefaultValues.error": "Failed to get values",
"form.field.required": "Field required",
"form.field.duplicate": "Value already exists",
- "form.field.minLength": "{{0}} character(s) minimum",
+ "form.field.minLength": "{{length}} character(s) minimum",
+ "form.field.maxLength": "{{length}} character(s) maximum",
"form.field.minValue": "The minimum value is {{0}}",
"form.field.maxValue": "The maximum value is {{0}}",
"form.field.invalidNumber": "Invalid number",
diff --git a/webapp/public/locales/fr/main.json b/webapp/public/locales/fr/main.json
index 21085ed4bd..ef12be54ec 100644
--- a/webapp/public/locales/fr/main.json
+++ b/webapp/public/locales/fr/main.json
@@ -123,7 +123,8 @@
"form.asyncDefaultValues.error": "Impossible d'obtenir les valeurs",
"form.field.required": "Champ requis",
"form.field.duplicate": "Cette valeur existe déjà",
- "form.field.minLength": "{{0}} caractère(s) minimum",
+ "form.field.minLength": "{{length}} caractère(s) minimum",
+ "form.field.maxLength": "{{length}} caractère(s) maximum",
"form.field.minValue": "La valeur minimum est {{0}}",
"form.field.maxValue": "La valeur maximum est {{0}}",
"form.field.invalidNumber": "Nombre invalide",
diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx
index f1af440491..6891123b8c 100644
--- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/AddDialog.tsx
@@ -157,7 +157,7 @@ function AddDialog({
rules={{
validate: (v) =>
validateString(v, {
- max: 20,
+ maxLength: 20,
specialChars: "-",
}),
}}
diff --git a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx
index 3405540a6e..7677a78c4f 100644
--- a/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx
+++ b/webapp/src/components/App/Singlestudy/explore/Modelization/BindingConstraints/BindingConstView/ConstraintFields.tsx
@@ -90,7 +90,7 @@ function Fields({ study, constraintId }: Props) {
rules={{
validate: (v) =>
validateString(v, {
- max: 20,
+ maxLength: 20,
specialChars: "-",
}),
}}
diff --git a/webapp/src/utils/validationUtils.ts b/webapp/src/utils/validationUtils.ts
index 5760f285ae..86fb294d8b 100644
--- a/webapp/src/utils/validationUtils.ts
+++ b/webapp/src/utils/validationUtils.ts
@@ -9,7 +9,7 @@ interface NumberValidationOptions {
max?: number;
}
-interface ValidationOptions {
+interface StringValidationOptions {
existingValues?: string[];
excludedValues?: string[];
isCaseSensitive?: boolean;
@@ -17,8 +17,8 @@ interface ValidationOptions {
specialChars?: string;
allowSpaces?: boolean;
editedValue?: string;
- min?: number;
- max?: number;
+ minLength?: number;
+ maxLength?: number;
}
////////////////////////////////////////////////////////////////
@@ -40,13 +40,13 @@ interface ValidationOptions {
* @param [options.specialChars="&()_-"] - A string representing additional allowed characters outside the typical alphanumeric scope.
* @param [options.allowSpaces=true] - Flags if spaces are allowed in the value.
* @param [options.editedValue=""] - The current value being edited, to exclude it from duplicate checks.
- * @param [options.min=0] - Minimum length required for the string. Defaults to 0.
- * @param [options.max=255] - Maximum allowed length for the string. Defaults to 255.
+ * @param [options.minLength=0] - Minimum length required for the string. Defaults to 0.
+ * @param [options.maxLength=255] - Maximum allowed length for the string. Defaults to 255.
* @returns True if validation is successful, or a localized error message if it fails.
*/
export function validateString(
value: string,
- options?: ValidationOptions,
+ options?: StringValidationOptions,
): string | true {
const {
existingValues = [],
@@ -56,8 +56,8 @@ export function validateString(
allowSpaces = true,
specialChars = "&()_-",
editedValue = "",
- min = 0,
- max = 255,
+ minLength = 0,
+ maxLength = 255,
} = options || {};
const trimmedValue = value.trim();
@@ -70,12 +70,12 @@ export function validateString(
return t("form.field.spacesNotAllowed");
}
- if (trimmedValue.length < min) {
- return t("form.field.minValue", { 0: min });
+ if (trimmedValue.length < minLength) {
+ return t("form.field.minLength", { length: minLength });
}
- if (trimmedValue.length > max) {
- return t("form.field.maxValue", { 0: max });
+ if (trimmedValue.length > maxLength) {
+ return t("form.field.maxLength", { length: maxLength });
}
// Compiles a regex pattern based on allowed characters and flags.
@@ -129,11 +129,11 @@ export function validatePassword(password: string): string | true {
}
if (trimmedPassword.length < 8) {
- return t("form.field.minValue", { 0: 8 });
+ return t("form.field.minLength", { length: 8 });
}
if (trimmedPassword.length > 50) {
- return t("form.field.maxValue", { 0: 50 });
+ return t("form.field.maxLength", { length: 50 });
}
if (!/[a-z]/.test(trimmedPassword)) {