From 1412737036a03cc4ef78fa88426aec62dd94b71f Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Tue, 10 Jun 2025 12:27:55 +0200 Subject: [PATCH] Date / Time validations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR ensures time fields are required when dates are set, using Oqtane validation and dynamically toggles the required attribute on time inputs when their corresponding date fields have values. Benefits: - Uses Oqtane's validation for a polished UX. - Reduces custom validation code. - Aligns with our internal form logic. - Tested across all date/time scenarios—works flawlessly! **Testing Confirmed:** - Date + Time Provided → Saves successfully. - No Date + No Time → Optional (no validation). - Date + No Time → Browser blocks submission with icon error. --- Oqtane.Client/Modules/Admin/Jobs/Edit.razor | 27 ++++++++++----------- Oqtane.Client/Modules/ModuleBase.cs | 10 ++++++++ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Jobs/Edit.razor b/Oqtane.Client/Modules/Admin/Jobs/Edit.razor index f0ff0a2c..26d96688 100644 --- a/Oqtane.Client/Modules/Admin/Jobs/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Jobs/Edit.razor @@ -56,7 +56,7 @@
- +
@@ -69,7 +69,7 @@
- +
@@ -82,7 +82,7 @@
- +
@@ -176,18 +176,18 @@ { job.Interval = int.Parse(_interval); } - job.StartDate = _startDate.HasValue && _startTime.HasValue - ? LocalToUtc(_startDate.Value.Date.Add(_startTime.Value.TimeOfDay)) - : null; + job.StartDate = _startDate.HasValue && _startTime.HasValue + ? LocalToUtc(_startDate.GetValueOrDefault().Date.Add(_startTime.GetValueOrDefault().TimeOfDay)) + : null; - job.EndDate = _endDate.HasValue && _endTime.HasValue - ? LocalToUtc(_endDate.Value.Date.Add(_endTime.Value.TimeOfDay)) - : null; + job.EndDate = _endDate.HasValue && _endTime.HasValue + ? LocalToUtc(_endDate.GetValueOrDefault().Date.Add(_endTime.GetValueOrDefault().TimeOfDay)) + : null; - job.NextExecution = _nextDate.HasValue && _nextTime.HasValue - ? LocalToUtc(_nextDate.Value.Date.Add(_nextTime.Value.TimeOfDay)) - : null; - job.RetentionHistory = int.Parse(_retentionHistory); + job.NextExecution = _nextDate.HasValue && _nextTime.HasValue + ? LocalToUtc(_nextDate.GetValueOrDefault().Date.Add(_nextTime.GetValueOrDefault().TimeOfDay)) + : null; + job.RetentionHistory = int.Parse(_retentionHistory); try { @@ -206,5 +206,4 @@ AddModuleMessage(Localizer["Message.Required.JobInfo"], MessageType.Warning); } } - } diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index 0dabafd3..a066d159 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -503,6 +503,10 @@ namespace Oqtane.Modules // date conversion methods public DateTime? UtcToLocal(DateTime? datetime) { + // Early return if input is null + if (datetime == null) + return null; + TimeZoneInfo timezone = null; try { @@ -519,11 +523,16 @@ namespace Oqtane.Modules { // The time zone ID was not found on the local computer } + return Utilities.UtcAsLocalDateTime(datetime, timezone); } public DateTime? LocalToUtc(DateTime? datetime) { + // Early return if input is null + if (datetime == null) + return null; + TimeZoneInfo timezone = null; try { @@ -540,6 +549,7 @@ namespace Oqtane.Modules { // The time zone ID was not found on the local computer } + return Utilities.LocalDateAndTimeAsUtc(datetime, timezone); }