diff --git a/DigitalLearningSolutions.Web/Controllers/Support/RequestSupportTicketController.cs b/DigitalLearningSolutions.Web/Controllers/Support/RequestSupportTicketController.cs index ceedb79af8..3895b3dca2 100644 --- a/DigitalLearningSolutions.Web/Controllers/Support/RequestSupportTicketController.cs +++ b/DigitalLearningSolutions.Web/Controllers/Support/RequestSupportTicketController.cs @@ -137,7 +137,7 @@ public IActionResult SetRequestSummary(DlsSubApplication dlsSubApplication, Requ // Check if RequestDescription is null or contains any default empty tags ("


"). // This ensures that when a user navigates to the submit page and returns to SetRequestSummary, // removing the description completely results in an actual empty value rather than leftover HTML tags. - if (requestDetailsmodel.RequestDescription == "


") + if (string.IsNullOrEmpty(StringHelper.StripHtmlTags(requestDetailsmodel.RequestDescription))) { ModelState.AddModelError("RequestDescription", "Please enter request description"); } @@ -246,7 +246,7 @@ public IActionResult SupportSummary(DlsSubApplication dlsSubApplication, Support var data = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.AddCustomWebForm("RequestSupportTicketCWF"), TempData - ).GetAwaiter().GetResult(); + ).GetAwaiter().GetResult(); var model = new SupportSummaryViewModel(data); return View("SupportTicketSummaryPage", model); } @@ -262,7 +262,7 @@ public IActionResult SubmitSupportSummary(DlsSubApplication dlsSubApplication, S var data = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.AddCustomWebForm("RequestSupportTicketCWF"), TempData - ).GetAwaiter().GetResult(); + ).GetAwaiter().GetResult(); data.GroupId = configuration.GetFreshdeskCreateTicketGroupId(); data.ProductId = configuration.GetFreshdeskCreateTicketProductId(); List RequestAttachmentList = new List(); @@ -354,7 +354,7 @@ private void setRequestSupportTicketData(RequestSupportTicketData requestSupport { foreach (var item in requestAttachmentmodel.RequestAttachment) { - totalFileSize = totalFileSize + item.SizeMb??0; + totalFileSize = totalFileSize + item.SizeMb ?? 0; } } foreach (var item in requestAttachmentmodel.ImageFiles) diff --git a/DigitalLearningSolutions.Web/Helpers/StringHelper.cs b/DigitalLearningSolutions.Web/Helpers/StringHelper.cs index c2affb6f74..82809fb671 100644 --- a/DigitalLearningSolutions.Web/Helpers/StringHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/StringHelper.cs @@ -26,8 +26,8 @@ public static string StripHtmlTags(string input) // Remove HTML tags string result = Regex.Replace(input, "<.*?>", string.Empty).Trim(); - - return string.IsNullOrEmpty(result) ? string.Empty : result; + result = System.Net.WebUtility.HtmlDecode(result); + return string.IsNullOrEmpty(result.Trim()) ? string.Empty : result; } } } diff --git a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts index 8577474744..129697c0af 100644 --- a/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts +++ b/DigitalLearningSolutions.Web/Scripts/frameworks/htmleditor.ts @@ -1,4 +1,4 @@ -import { Jodit } from 'jodit'; +import { Jodit } from 'jodit'; import DOMPurify from 'dompurify'; let jodited = false; @@ -70,5 +70,31 @@ if (jodited === false) { const clean = DOMPurify.sanitize(editor.editor.innerHTML); editor.editor.innerHTML = clean; }); + const textarea = document.querySelector('.nhsuk-textarea.html-editor.nhsuk-input--error') as HTMLTextAreaElement | null; + if (textarea) { + const editorDiv = document.querySelector('.jodit-container.jodit.jodit_theme_default.jodit-wysiwyg_mode') as HTMLDivElement | null; + editorDiv?.classList.add('jodit-container', 'jodit', 'jodit_theme_default', 'jodit-wysiwyg_mode', 'jodit-error'); + } + + const summary = document.querySelector('.nhsuk-list.nhsuk-error-summary__list') as HTMLDivElement | null; + + if (summary) { + summary.addEventListener('click', (e: Event) => { + if (textarea) { + const textareaId = textarea.id.toString(); + const target = e.target as HTMLElement; + if (target.tagName.toLowerCase() === 'a') { + const href = (target as HTMLAnchorElement).getAttribute('href'); + + if (href && href.includes(textareaId)) { + const editorArea = document.querySelector('.jodit-wysiwyg') as HTMLDivElement | null; + editorArea?.focus(); + editorArea?.scrollIntoView({ behavior: 'smooth', block: 'center' }); + e.preventDefault(); + } + } + } + }); + } } } diff --git a/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs b/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs index 66ff813868..dcb388f3ae 100644 --- a/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs +++ b/DigitalLearningSolutions.Web/Services/ImportCompetenciesFromFileService.cs @@ -74,11 +74,14 @@ private void PreProcessCompetencyRow(CompetencyTableRow competencyRow, List else { var groupName = (string)(competencyRow?.CompetencyGroup); - originalIndex = existingGroups.IndexOf(groupName); - newIndex = newGroups.IndexOf(groupName); - if (originalIndex != newIndex) + if (!string.IsNullOrWhiteSpace(groupName)) { - competencyRow.Reordered = true; + originalIndex = existingGroups.IndexOf(groupName); + newIndex = newGroups.IndexOf(groupName); + if (originalIndex != newIndex) + { + competencyRow.Reordered = true; + } } } } diff --git a/DigitalLearningSolutions.Web/Styles/jodit.scss b/DigitalLearningSolutions.Web/Styles/jodit.scss index 8e0ed889dd..076a7f0053 100644 --- a/DigitalLearningSolutions.Web/Styles/jodit.scss +++ b/DigitalLearningSolutions.Web/Styles/jodit.scss @@ -1 +1,6 @@ @use "jodit/build/jodit.min"; + +.jodit-error { + border: 2px solid red !important; + border-radius: 4px; +} diff --git a/DigitalLearningSolutions.Web/ViewModels/Support/RequestSupportTicket/RequestSummaryViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Support/RequestSupportTicket/RequestSummaryViewModel.cs index 04371b7998..54b5598e23 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Support/RequestSupportTicket/RequestSummaryViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Support/RequestSupportTicket/RequestSummaryViewModel.cs @@ -21,7 +21,6 @@ public RequestSummaryViewModel(RequestSupportTicketData data) [Required(ErrorMessage = "Please enter request summary")] public string? RequestSubject { get; set; } - [Required(ErrorMessage = "Please enter request description")] public string? RequestDescription { get; set; } public int? RequestTypeId { get; set; } diff --git a/DigitalLearningSolutions.Web/Views/Support/RequestSupportTicket/RequestSummary.cshtml b/DigitalLearningSolutions.Web/Views/Support/RequestSupportTicket/RequestSummary.cshtml index 316f30e547..a66ce2019f 100644 --- a/DigitalLearningSolutions.Web/Views/Support/RequestSupportTicket/RequestSummary.cshtml +++ b/DigitalLearningSolutions.Web/Views/Support/RequestSupportTicket/RequestSummary.cshtml @@ -40,17 +40,15 @@ autocomplete="given-name" css-class="" required="true" /> - - - - + +