From 5eab061367ca9f5783b1ddc332e5690b94455385 Mon Sep 17 00:00:00 2001 From: Nafis Zaman Date: Mon, 2 Dec 2024 17:26:49 -0800 Subject: [PATCH 1/4] Add date finalizer to handle multiple delimiters --- src/components/interface/Form.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/interface/Form.tsx b/src/components/interface/Form.tsx index 78df8f85..be7c6368 100644 --- a/src/components/interface/Form.tsx +++ b/src/components/interface/Form.tsx @@ -230,12 +230,26 @@ namespace Form { } export const IDENTITY_FINALIZER = (value: string) => value; + export const DATE_FINALIZER = (value: string) => { + let valueParts: string[] = []; + const validDelimters = ['/', '-']; + for (const delimiter of validDelimters) { + valueParts = value.split(delimiter); + if (valueParts.length === 3) { + break; + } + } + + const [mm, dd, yyyy] = valueParts; + return `${mm}/${dd}/${yyyy}`; + }; + export const EMAIL_VALIDATOR = (value: string) => Validators.validate(value, Validators.Types.Email); export const PASSWORD_VALIDATOR = (value: string) => Validators.validatePassword(value); export const DATE_VALIDATOR = (value: string) => Validators.validate(value, Validators.Types.Date); export const NON_EMPTY_VALIDATOR = (value: string) => Validators.validate(value, Validators.Types.Length, 1); - + export const email = (id: string, text: string, tooltip?: string, assist?: () => void, assistText?: string): Item => ({ id, text, @@ -262,7 +276,7 @@ namespace Form { text, tooltip, validator: DATE_VALIDATOR, - finalizer: IDENTITY_FINALIZER, + finalizer: DATE_FINALIZER, assist, assistText, }); From d972e04f21a3f2954a30e550105e41c4414767ec Mon Sep 17 00:00:00 2001 From: Nafis Zaman Date: Mon, 2 Dec 2024 17:27:22 -0800 Subject: [PATCH 2/4] Improve date validator to reject invalid dates --- src/util/Validator.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/util/Validator.ts b/src/util/Validator.ts index 9081959d..801f09e7 100644 --- a/src/util/Validator.ts +++ b/src/util/Validator.ts @@ -151,8 +151,19 @@ export namespace Validators { case Types.Email: return /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value); case Types.Date: - // TODO: validate that it's a real date (e.g. 02/30/2000 should not pass) - return /^(0[1-9]|1[012])(\/|-)(0[1-9]|[12][0-9]|3[01])(\/|-)(19|20)\d{2}$/.test(value); + // Ensure it matches the expected format + const regexRes = /^(0[1-9]|1[012])(?:\/|-)(0[1-9]|[12][0-9]|3[01])(?:\/|-)((?:19|20)\d{2})$/.exec(value); + if (regexRes === null) return false; + + // Ensure it's a valid date + // Date constructor will rollover invalid dates, like 2024-02-30 to 2024-03-01, so ensure the individual parts didn't change + const [m, d, y] = regexRes.slice(1).map(s => parseInt(s)); + const dateObj = new Date(Date.UTC(y, m - 1, d)); + return !isNaN(dateObj.getTime()) && + dateObj.getUTCFullYear() === y && + (dateObj.getUTCMonth() + 1) === m && + dateObj.getUTCDate() === d; + default: return false; } From 4a80f21aeefedb8c4740392051c10eabd6a68a04 Mon Sep 17 00:00:00 2001 From: Nafis Zaman Date: Mon, 2 Dec 2024 17:35:42 -0800 Subject: [PATCH 3/4] Bump version to 2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8f13f298..c0d4f201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simulator", - "version": "2.0.1", + "version": "2.0.2", "sideEffects": false, "main": "dist/index.js", "author": "KISS Institute for Practical Robotics", From 1b23b6111b301c68657a73dc79594c85fa88979e Mon Sep 17 00:00:00 2001 From: Nafis Zaman Date: Tue, 3 Dec 2024 09:35:03 -0800 Subject: [PATCH 4/4] Fix linter violation --- src/util/Validator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/Validator.ts b/src/util/Validator.ts index 801f09e7..20f8f2a4 100644 --- a/src/util/Validator.ts +++ b/src/util/Validator.ts @@ -150,7 +150,7 @@ export namespace Validators { return value.length >= length; case Types.Email: return /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value); - case Types.Date: + case Types.Date: { // Ensure it matches the expected format const regexRes = /^(0[1-9]|1[012])(?:\/|-)(0[1-9]|[12][0-9]|3[01])(?:\/|-)((?:19|20)\d{2})$/.exec(value); if (regexRes === null) return false; @@ -163,7 +163,7 @@ export namespace Validators { dateObj.getUTCFullYear() === y && (dateObj.getUTCMonth() + 1) === m && dateObj.getUTCDate() === d; - + } default: return false; }