diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/RoadmapController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/RoadmapController.cs index 319c8938c..bd7261a87 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/RoadmapController.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/RoadmapController.cs @@ -99,7 +99,7 @@ public async Task AddUpdate(UpdateViewModel update) RoadmapTypeId = update.RoadmapTypeId, }; var roadmapId = await this.roadmapService.AddRoadmap(roadmap); - return this.RedirectToAction("EditUpdate", new { id = roadmapId }); + return this.RedirectToAction("Details", new { id = roadmapId }); } /// @@ -160,7 +160,7 @@ public async Task EditUpdate(UpdateViewModel update) Id = update.Id, }; await this.roadmapService.UpdateRoadmap(roadmap); - return this.RedirectToAction("EditUpdate", new { roadmap.Id }); + return this.RedirectToAction("Details", new { roadmap.Id }); } /// @@ -202,6 +202,18 @@ public async Task Updates(string searchTerm = null) return this.View(model); } + /// + /// The Details. + /// + /// The id. + /// The . + [HttpGet] + public async Task Details(int id) + { + var roadmap = await this.roadmapService.GetIdAsync(id); + return this.View(roadmap); + } + /// /// The UploadFile. /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IRoadmapService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IRoadmapService.cs index cb96b6037..a0606ebc3 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IRoadmapService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IRoadmapService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using LearningHub.Nhs.Models.Entities; + using LearningHub.Nhs.Models.RoadMap; /// /// Defines the . @@ -36,6 +37,13 @@ public interface IRoadmapService /// The . Task> GetUpdates(); + /// + /// The GetIdAsync. + /// + /// The id. + /// The . + Task GetIdAsync(int id); + /// /// The UpdateRoadmap. /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index 1fd9ba346..bc9b08b3f 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/RoadmapService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/RoadmapService.cs index bf4878d8b..48507ae31 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/RoadmapService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/RoadmapService.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using LearningHub.Nhs.AdminUI.Interfaces; using LearningHub.Nhs.Models.Entities; + using LearningHub.Nhs.Models.RoadMap; using Newtonsoft.Json; /// @@ -134,6 +135,34 @@ public async Task> GetUpdates() return viewmodel; } + /// + /// The GetIdAsync. + /// + /// The id. + /// The . + public async Task GetIdAsync(int id) + { + RoadMapViewModel viewmodel = null; + + var client = await this.LearningHubHttpClient.GetClientAsync(); + var request = $"Roadmap/GetRoadMapsById/{id}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + /// /// The UpdateRoadmap. /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/Edit.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/Edit.cshtml index 19ed8d399..75f4cddf2 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/Edit.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/Edit.cshtml @@ -3,458 +3,448 @@ @using LearningHub.Nhs.Models.Enums @using Newtonsoft.Json @{ - var page = Model.CatalogueNodeVersionId == 0 ? CatalogueNavPage.Add : CatalogueNavPage.Edit; - ViewData["Title"] = page == CatalogueNavPage.Add ? "Add catalogue" : "Edit catalogue"; - var baseUrl = _settings.Value.LearningHubUrl + "catalogue/"; - var url = baseUrl + (Model.Url ?? ""); - var aToZ = (int)CatalogueOrder.AlphabeticalAscending; - var keywords = Model.Keywords ?? new List(); - var Providers = Model.Providers; - var CatalogueNodeVersionProviderId = Model.CatalogueNodeVersionProvider?.ProviderId ?? 0; - var CatalogueNodeVersionProvider = Model.CatalogueNodeVersionProvider; - var action = page.ToString(); - var keywordsJson = Html.Raw(JsonConvert.SerializeObject(keywords)); - var imageBaseUrl = "/file/download/CatalogueImageDirectory/"; - var lastModifiedDate = Model.LastModifiedDate?.ToString("dd MMM yyyy"); + var page = Model.CatalogueNodeVersionId == 0 ? CatalogueNavPage.Add : CatalogueNavPage.Edit; + ViewData["Title"] = page == CatalogueNavPage.Add ? "Add catalogue" : "Edit catalogue"; + var baseUrl = _settings.Value.LearningHubUrl + "catalogue/"; + var url = baseUrl + (Model.Url ?? ""); + var aToZ = (int)CatalogueOrder.AlphabeticalAscending; + var keywords = Model.Keywords ?? new List(); + var Providers = Model.Providers; + var CatalogueNodeVersionProviderId = Model.CatalogueNodeVersionProvider?.ProviderId ?? 0; + var CatalogueNodeVersionProvider = Model.CatalogueNodeVersionProvider; + var action = page.ToString(); + var keywordsJson = Html.Raw(JsonConvert.SerializeObject(keywords)); + var imageBaseUrl = "/file/download/CatalogueImageDirectory/"; + var lastModifiedDate = Model.LastModifiedDate?.ToString("dd MMM yyyy"); } @section SideMenu { - @{ - await Html.RenderPartialAsync("_NavSection"); - } + @{ + await Html.RenderPartialAsync("_NavSection"); + } } @if (!string.IsNullOrEmpty(ViewBag.ErrorMessage)) { - + } @if (page == CatalogueNavPage.Edit) { -
-
-

@Model.Name

+
+
+

@Model.Name

+
-
} @{ - await Html.RenderPartialAsync("_CatalogueNav.cshtml", new CatalogueNavViewModel { Page = page, CatalogueId = Model.CatalogueNodeVersionId }); + await Html.RenderPartialAsync("_CatalogueNav.cshtml", new CatalogueNavViewModel { Page = page, CatalogueId = Model.CatalogueNodeVersionId }); }
-
- - - - -
-
-
- @if (page == CatalogueNavPage.Edit) - { - var idString = Model.CatalogueNodeVersionId.ToString(); - var paddedIdString = idString.Length > 3 ? idString : idString.PadLeft(3, '0'); - ID: @paddedIdString - } - else - { - NEW - } + + + + + +
+
+
+ @if (page == CatalogueNavPage.Edit) + { + var idString = Model.CatalogueNodeVersionId.ToString(); + var paddedIdString = idString.Length > 3 ? idString : idString.PadLeft(3, '0'); + ID: @paddedIdString + } + else + { + NEW + } +
+ @if (page == CatalogueNavPage.Add || Model.Hidden) + { + Hidden + } + @if (lastModifiedDate != null) + { +

Last modified on: @lastModifiedDate

+ } +
- @if (page == CatalogueNavPage.Add || Model.Hidden) - { - Hidden - } - @if (lastModifiedDate != null) - { -

Last modified on: @lastModifiedDate

- } -
-
- - @if (!ViewData.ModelState.IsValid) - { -
This form failed to save because there are errors below.
- } -
-
- -

You can enter a maximum of 255 characters including spaces

- - -
-
-
-
- - @if (page == CatalogueNavPage.Add) - { - - } - else - { - - } - -
-
- @if (Model.Status == VersionStatusEnum.Published && !Model.Hidden) + @if (!ViewData.ModelState.IsValid) { - +
This form failed to save because there are errors below.
} - else - { -

- } -
-
-
-
- -
-
-
-
- - -
-
-
-
- -
-
-
-
- -
-
-
-
- - - Only the first 3,000 characters of the description will be used by search - -
-
-
-
- -

- Add one or more relevant keywords to help learners find this catalogue, ensuring that the keyword is specifically related to the catalogue rather than the resources associated with it. A maximum of 5 keywords can be added. Enter one keyword and add it before entering another. -

-
-
- -
- + +
+
+ +

You can enter a maximum of 255 characters including spaces

+ +
-
-
-
- - -
+
+
+ + @if (page == CatalogueNavPage.Add) + { + + } + else + { + + } + +
+
+ @if (Model.Status == VersionStatusEnum.Published && !Model.Hidden) + { + + } + else + { +

+ } +
-
-
- -
+
+
+ +
+
+
+
+ + +
+
+
+ +
+
+
+
+ +
+
+
+
+ + + Only the first 3,000 characters of the description will be used by search + +
+
+
+
+ +

+ Add one or more relevant keywords to help learners find this catalogue, ensuring that the keyword is specifically related to the catalogue rather than the resources associated with it. A maximum of 5 keywords can be added. Enter one keyword and add it before entering another. +

+
+
+ +
+ +
+
+
+
+
+ + +
+
+
+
+ +
+
-
-
-

You can enter a maximum of 50 characters per keyword.

-
- @{ - var i = 0; - } - @foreach (var keyword in keywords) - { -
-

@keyword

- -
- } +
+

You can enter a maximum of 50 characters per keyword.

+
+ @{ + var i = 0; + } + @foreach (var keyword in keywords) + { +
+

@keyword

+ + +
+ } +
+
-
-
-
+
-
-
- -
-
+
+
+ +
+
-
-
-
- @if (!Model.RestrictedAccess) - { - - } - else - { - - } - Unrestricted access (default) -
-
- @if (Model.RestrictedAccess) - { - - } - else +
+
+
+ @if (!Model.RestrictedAccess) + { + + } + else + { + + } + Unrestricted access (default) +
+
+ @if (Model.RestrictedAccess) + { + + } + else + { + + } + Restricted access +
+
+
+ @if (!Model.HasUserGroup) { - +
+

There are no user groups associated with this catalogue. You can add some in the User Groups tab.

+
} - Restricted access -
-
-
- @if (!Model.HasUserGroup) - { -
-

There are no user groups associated with this catalogue. You can add some in the User Groups tab.

- } -
-
+
-
-
- -

When applicable please select the provider of this content. This will allow a contributor to flag content from a specific provider.

-

This will enable learners to search for content produced by organisations and help separate learning resources from community contributions.

-

Developed with;

-
-
+
+
+ +

When applicable please select the provider of this content. This will allow a contributor to flag content from a specific provider.

+

This will enable learners to search for content produced by organisations and help separate learning resources from community contributions.

+

Developed with;

+
+
-
-
- @if (Providers != null && Providers.Count() > 0) - { -
- @foreach (var provider in Providers) - { - - @provider.Name -
- } - - Not applicable +
+
+ @if (Providers != null && Providers.Count() > 0) + { +
+ @foreach (var provider in Providers) + { + + @provider.Name +
+ } + + Not applicable +
+ } +
- }
-
-
-
-
- @if (page == CatalogueNavPage.Add) - { - - } - else - { - - } -
-
- -
+
+
+ @if (page == CatalogueNavPage.Add) + { + + } + else + { + + } +
+
+ +
@section Scripts { - - + + } diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Log/Index.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Log/Index.cshtml index 8e9c75ae2..8f3eb95d3 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Log/Index.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Log/Index.cshtml @@ -23,6 +23,8 @@ + @if (Model.Results != null) + { @foreach (var item in Model.Results.Items) { @@ -46,6 +48,7 @@ } + }
diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Details.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Details.cshtml new file mode 100644 index 000000000..983a1abc0 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Details.cshtml @@ -0,0 +1,98 @@ +@model LearningHub.Nhs.Models.RoadMap.RoadMapViewModel; +@using LearningHub.Nhs.AdminUI.Services + +@{ + ViewData["Title"] = "Details"; +} +@section SideMenu { + @{ + await Html.RenderPartialAsync("_NavSection"); + } +} + +
+
+   Go back +
+ +
+
+ @{ + string noneVal = ""; + } +
+
+
ID @Model.Id
+ @ViewBag.UpdateSaveError +
+
+ Title +
+
+ @Html.DisplayFor(model => model.Title) +
+
+ Date +
+
+ @Html.DisplayFor(model => model.RoadmapDate) +
+
+ Feature Image +
+
+ +
+
+ Description +
+
+ @Html.Raw(Model.Description) +
+
+ Status +
+ + + @if (Model.Published) + { +
+ Published +
+ } + else + { +
+ Not Published +
+ } +
+ Create User +
+
+ @Html.DisplayFor(model => model.CreateUserName) +
+
+ Create Date +
+
+ @Html.DisplayFor(model => model.CreateDate) +
+
+ Amend User +
+
+ @Html.DisplayFor(model => model.AmendUserName) +
+
+ Amend Date +
+
+ @Html.DisplayFor(model => model.AmendDate) +
+
+
+
+ +
+ diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Updates.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Updates.cshtml index 5a7a801b1..767896ab4 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Updates.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Roadmap/Updates.cshtml @@ -1,68 +1,70 @@ @model LearningHub.Nhs.Models.Paging.TablePagingViewModel @{ - ViewData["Title"] = "Service updates and releases"; - ViewData["CurrentPage"] = Model.Paging.CurrentPage; - var searchTerm = ViewData["SearchTerm"]; + ViewData["Title"] = "Service updates and releases"; + ViewData["CurrentPage"] = Model.Paging.CurrentPage; + var searchTerm = ViewData["SearchTerm"]; } -@section Styles{ - +@section Styles { + } @section SideMenu { - @{await Html.RenderPartialAsync("_NavSection"); } + @{ + await Html.RenderPartialAsync("_NavSection"); + } }
-
-
- Updates -
+
+ - +
+
- - - - - - +
Published
+ + + + + - - - - @foreach (var item in Model.Results.Items) + + + + @foreach (var item in Model.Results.Items) + { + + + + - - - - + } - -
Published
+ @Html.ActionLink(item.Title.ToString(), "Details", new { id = item.Id }) + + @Html.ActionLink(item.RoadmapDate.Value.ToString("dd MMM yyyy"), "Details", new { id = item.Id }) + + @if (item.Published) { -
- @Html.ActionLink(item.Title.ToString(), "EditUpdate", new { id = item.Id }) - - @Html.ActionLink(item.RoadmapDate.Value.ToString("dd MMM yyyy"), "EditUpdate", new { id = item.Id }) - - @if (item.Published) - { - - } - else - { - - } -
+ else + { + + } + + + } + +
@section Scripts { - - + + } diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml index 995e1f42a..924c58475 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml @@ -13,9 +13,9 @@ sideMenu = "settings"; break; case "roadmap": + sideMenu = "settings"; if (activeItem.Contains("update")) { - sideMenu = "settings"; controller = "updates"; } break; diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs index c8c9b447b..8544241bd 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs @@ -73,17 +73,10 @@ public async Task DownloadResource(string filePath, string fileNa } var file = await this.fileService.DownloadFileAsync(filePath, fileName); + if (file != null) { - // Set response headers. - this.Response.ContentType = file.ContentType; - this.Response.ContentLength = file.ContentLength; - var contentDisposition = new ContentDispositionHeaderValue("attachment") { FileNameStar = fileName }; - this.Response.Headers["Content-Disposition"] = contentDisposition.ToString(); - - // Stream the file in chunks with periodic flushes to keep the connection active. - await this.StreamFileWithKeepAliveAsync(file.Content, this.Response.Body, this.HttpContext.RequestAborted); - return this.Ok(); + return !string.IsNullOrEmpty(file.DownloadUrl) ? this.Redirect(file.DownloadUrl) : this.File(file.Content, file.ContentType, fileName); } else { @@ -119,15 +112,7 @@ public async Task DownloadResourceAndRecordActivity(int resourceV }; await this.activityService.CreateResourceActivityAsync(activity); - // Set response headers. - this.Response.ContentType = file.ContentType; - this.Response.ContentLength = file.ContentLength; - var contentDisposition = new ContentDispositionHeaderValue("attachment") { FileNameStar = fileName }; - this.Response.Headers["Content-Disposition"] = contentDisposition.ToString(); - - // Stream the file in chunks with periodic flushes to keep the connection active. - await this.StreamFileWithKeepAliveAsync(file.Content, this.Response.Body, this.HttpContext.RequestAborted); - return this.Ok(); + return !string.IsNullOrEmpty(file.DownloadUrl) ? this.Redirect(file.DownloadUrl) : this.File(file.Content, file.ContentType, fileName); } else { diff --git a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs index 2fca0012e..12d9973ac 100644 --- a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs @@ -587,8 +587,7 @@ public async Task RequestPreviewAccess(CatalogueRequestAccessView [Route("/allcatalogue/{filterChar}")] public async Task GetAllCatalogue(string filterChar = "a") { - var pageSize = this.settings.AllCataloguePageSize; - var catalogues = await this.catalogueService.GetAllCatalogueAsync(filterChar, pageSize); + var catalogues = await this.catalogueService.GetAllCatalogueAsync(filterChar); return this.View("allcatalogue", catalogues); } diff --git a/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs b/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs index 3e2753448..c9b3aa7bc 100644 --- a/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs +++ b/LearningHub.Nhs.WebUI/Helpers/CommonValidationErrorMessages.cs @@ -58,7 +58,7 @@ public static class CommonValidationErrorMessages /// /// Grade Required. /// - public const string GradeRequired = "Select a grade"; + public const string GradeRequired = "Select a pay band. You can find this information from your paper payslip or online via ESR"; /// /// Primary specialty Not Applicable. diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs index 635eee151..e7770fd86 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs @@ -143,8 +143,7 @@ public interface ICatalogueService /// The GetAllCatalogueAsync. /// /// The letter. - /// The pageSize. /// The allcatalogue result based on letters. - Task GetAllCatalogueAsync(string filterChar, int pageSize); + Task GetAllCatalogueAsync(string filterChar); } } diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index d8698b4f9..1461f089a 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs b/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs index 8036e9320..1a4d76679 100644 --- a/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs +++ b/LearningHub.Nhs.WebUI/Models/FileDownloadResponse.cs @@ -21,5 +21,10 @@ public class FileDownloadResponse /// Gets or sets the ContentType. ///
public long ContentLength { get; set; } + + /// + /// Gets or sets when downloading large files, a SAS URL is returned so the client can download directly from Azure Files. + /// + public string DownloadUrl { get; set; } } } \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue b/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue index adbcd76f2..6c2a875c8 100644 --- a/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue +++ b/LearningHub.Nhs.WebUI/Scripts/vuesrc/notification/notification.vue @@ -45,7 +45,7 @@
- +
diff --git a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs index 615363cfd..a8a6d3055 100644 --- a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs @@ -607,14 +607,13 @@ public async Task RemoveUserFromRestrictedAccessUse /// GetAllCatalogueAsync. ///
/// The filterChar. - /// the pageSize. - /// A representing the result of the asynchronous operation. - public async Task GetAllCatalogueAsync(string filterChar, int pageSize) + /// /// A representing the result of the asynchronous operation. + public async Task GetAllCatalogueAsync(string filterChar) { AllCatalogueResponseViewModel viewmodel = new AllCatalogueResponseViewModel { }; var client = await this.LearningHubHttpClient.GetClientAsync(); - var request = $"catalogue/allcatalogues/{pageSize}/{filterChar}"; + var request = $"catalogue/allcatalogues/{filterChar}"; var response = await client.GetAsync(request).ConfigureAwait(false); if (response.IsSuccessStatusCode) diff --git a/LearningHub.Nhs.WebUI/Services/FileService.cs b/LearningHub.Nhs.WebUI/Services/FileService.cs index 1e01a0aaf..a09195d62 100644 --- a/LearningHub.Nhs.WebUI/Services/FileService.cs +++ b/LearningHub.Nhs.WebUI/Services/FileService.cs @@ -1,17 +1,13 @@ namespace LearningHub.Nhs.WebUI.Services { using System; - using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; - using System.Threading; using System.Threading.Tasks; - using System.Threading.Tasks.Dataflow; - using Azure; - using Azure.Storage; using Azure.Storage.Files.Shares; using Azure.Storage.Files.Shares.Models; + using Azure.Storage.Sas; using LearningHub.Nhs.Models.Resource; using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Interfaces; @@ -145,27 +141,19 @@ public async Task DownloadFileAsync(string filePath, strin try { - if (fileSize <= 900 * 1024 * 1024) + var response = new FileDownloadResponse { - // For smaller files, download the entire file as a stream. - var response = await file.DownloadAsync(); - return new FileDownloadResponse - { - Content = response.Value.Content, - ContentType = properties.Value.ContentType, - ContentLength = fileSize, - }; - } - else + ContentType = properties.Value.ContentType, + ContentLength = fileSize, + Content = await file.OpenReadAsync(), + }; + + if (fileSize >= 999 * 1024 * 1024) { - // For large files, open a read stream - return new FileDownloadResponse - { - Content = await file.OpenReadAsync(), - ContentType = properties.Value.ContentType, - ContentLength = fileSize, - }; + response.DownloadUrl = this.GenerateSasUriForFile(file); } + + return response; } catch (Exception ex) { @@ -305,12 +293,12 @@ private async Task MoveOutPutDirectoryToArchive(List allDirectoryRef) } else { - var destinationFileClient = archiveDirectory.GetFileClient(fileItem.Name); - var uri = sourceFileClient.GenerateSasUri(Azure.Storage.Sas.ShareFileSasPermissions.Read, DateTime.UtcNow.AddHours(24)); + var destinationFileClient = archiveDirectory.GetFileClient(fileItem.Name); + var uri = sourceFileClient.GenerateSasUri(Azure.Storage.Sas.ShareFileSasPermissions.Read, DateTime.UtcNow.AddHours(24)); - await destinationFileClient.StartCopyAsync(uri); + await destinationFileClient.StartCopyAsync(uri); - await WaitForCopyAsync(destinationFileClient); + await WaitForCopyAsync(destinationFileClient); } } @@ -461,5 +449,23 @@ private async Task FindFileAsync(string filePath, string fileNa return null; } + + private string GenerateSasUriForFile(ShareFileClient fileClient) + { + if (fileClient.CanGenerateSasUri) + { + ShareSasBuilder sasBuilder = new ShareSasBuilder(ShareFileSasPermissions.Read, DateTimeOffset.UtcNow.AddMinutes(20)) + { + Protocol = SasProtocol.Https, + }; + + Uri sasUri = fileClient.GenerateSasUri(sasBuilder); + return sasUri.ToString(); + } + else + { + throw new InvalidOperationException("Unable to generate SAS URI for the file."); + } + } } } \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss index 03c179388..4cb2822fe 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss @@ -411,6 +411,90 @@ li.autosuggestion-option:last-of-type { .autosuggestion-menu { top: 100%; } + + .nhsuk-header__not-mobile { + display: none; + } + + .nhsuk-header__mobile-only-nav { + display: flex; + order: 1; + justify-content: space-around; + gap: 0 px2rem(16); + align-items: flex-start; + flex-wrap: wrap; + width: px2rem(166); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__menu { + margin-right: px2rem(12); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__search-toggle { + margin-left: px2rem(12); + } + + .nhsuk-header__break { + display: none; + } + + .nhsuk-header__mobile-break { + display: block; + width: 100%; + height: 0; + } + + .nhsuk-header__link--service { + flex-direction: column; + align-items: flex-start; + } + + .nhsuk-header__notification-dot { + top: px2rem(13); + left: px2rem(100); + } + + .nhsuk-header__service-name { + padding: px2rem(12) 0 0; + } + + .nhsuk-header__search-toggle { + position: relative; + height: px2rem(40); + order: 2; + padding: px2rem(7) px2rem(10) 0; + margin: 0 + } + + .nhsuk-header__search .nhsuk-search__submit { + padding-top: nhsuk-spacing(1); + } + + .nhsuk-header__menu { + order: 3; + } + + .nhsuk-header__search { + order: 4; + width: 100%; + flex-grow: 1; + margin: px2rem(16) px2rem(-16) 0; + border-bottom: 1px solid $color_nhsuk-grey-4; + } + + #header-mobile-search-control { + display: block; + opacity: 0; + position: absolute; + } + + #header-mobile-search-control:checked ~ .nhsuk-header__search .nhsuk-header__search-wrap { + display: block; + } + + .nhsuk-width-container.nhsuk-header__container.app-width-container { + padding-bottom: 0; + } } /* mobile */ diff --git a/LearningHub.Nhs.WebUI/Views/Account/ChangePassword.cshtml b/LearningHub.Nhs.WebUI/Views/Account/ChangePassword.cshtml index d7819faea..6bf906653 100644 --- a/LearningHub.Nhs.WebUI/Views/Account/ChangePassword.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Account/ChangePassword.cshtml @@ -1,6 +1,7 @@ @model LearningHub.Nhs.WebUI.Models.Account.PasswordValidateViewModel @{ + ViewData["DisableValidation"] = true; ViewData["Title"] = "Account - Change password"; var errorHasOccurred = !ViewData.ModelState.IsValid; } diff --git a/LearningHub.Nhs.WebUI/Views/Account/CreateAccountEmailVerification.cshtml b/LearningHub.Nhs.WebUI/Views/Account/CreateAccountEmailVerification.cshtml index 06da30f1b..752364bf7 100644 --- a/LearningHub.Nhs.WebUI/Views/Account/CreateAccountEmailVerification.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Account/CreateAccountEmailVerification.cshtml @@ -37,13 +37,13 @@

Create an account

Information: -

Ideally you should provide a work email address so that your registration results in the most appropriate access.

+

Providing a work email address will ensure your registration receives the appropriate access.

diff --git a/LearningHub.Nhs.WebUI/Views/Account/CreateAccountRegistrationInformation.cshtml b/LearningHub.Nhs.WebUI/Views/Account/CreateAccountRegistrationInformation.cshtml index 12d51bbd2..d39a34171 100644 --- a/LearningHub.Nhs.WebUI/Views/Account/CreateAccountRegistrationInformation.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Account/CreateAccountRegistrationInformation.cshtml @@ -24,7 +24,7 @@

General user account

- General users can access resources made available by contributors to all users. + General users have access to the resources that contributors have made available for public access.

Required information

@@ -40,12 +40,12 @@

Additional information needed

    -
  • Qualifying work email address (e.g. NHS email address)
  • +
  • Qualifying work email address (for example, NHS email address)
  • Current role
  • Professional registration number (if applicable)
  • -
  • Grade / Band
  • +
  • Grade or Band
  • Start date
  • -
  • Primary specialty (if applicable)
  • +
  • Primary speciality (if applicable)
  • Country
  • Place of work details
  • diff --git a/LearningHub.Nhs.WebUI/Views/Account/ForgotUserPassword.cshtml b/LearningHub.Nhs.WebUI/Views/Account/ForgotUserPassword.cshtml index 91160751e..27e886f88 100644 --- a/LearningHub.Nhs.WebUI/Views/Account/ForgotUserPassword.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Account/ForgotUserPassword.cshtml @@ -5,6 +5,7 @@ @model ForgotPasswordViewModel; @{ + ViewData["DisableValidation"] = true; ViewData["Title"] = "ForgotPassword"; var errorHasOccurred = !ViewData.ModelState.IsValid; } diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/RequestAccess.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/RequestAccess.cshtml index dc7a202e3..b67917e35 100644 --- a/LearningHub.Nhs.WebUI/Views/Catalogue/RequestAccess.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/RequestAccess.cshtml @@ -2,68 +2,82 @@ @using LearningHub.Nhs.WebUI.Models.Catalogue @using LearningHub.Nhs.Models.Enums @{ - ViewData["Title"] = "Request Access"; + ViewData["Title"] = "Request Access"; } -@section styles{ - +@section styles { + }
    -
    - -

    Catalogue access request

    +
    + +

    Catalogue access request

    -
    - @using (Html.BeginForm("RequestAccessPost", "Catalogue", FormMethod.Post)) - { - @if (Model.CatalogueAccessRequest != null && Model.CatalogueAccessRequest.Status == CatalogueAccessRequestStatus.Rejected) - { -

    Your last request to access this catalogue was denied on @Model.CatalogueAccessRequest.DateRejected.Value.ToString("dd MMM yyyy") for the following reason:

    -

    @Model.CatalogueAccessRequest.ResponseMessage

    - } +
    + @using (Html.BeginForm("RequestAccessPost", "Catalogue", FormMethod.Post)) + { + @if (Model.CatalogueAccessRequest != null && Model.CatalogueAccessRequest.Status == CatalogueAccessRequestStatus.Rejected) + { +

    Your last request to access this catalogue was denied on @Model.CatalogueAccessRequest.DateRejected.Value.ToString("dd MMM yyyy") for the following reason:

    +

    @Model.CatalogueAccessRequest.ResponseMessage

    + } + else if (Model.CatalogueAccessRequest != null && Model.CatalogueAccessRequest.Status == CatalogueAccessRequestStatus.Pending) + { +

    Your access request which was sent on @Model.CatalogueAccessRequest.DateRequested.ToString("dd MMM yyyy") is pending a decision.

    +

    If you need further information contact support

    + } -

    You are requesting access to the @Model.CatalogueName catalogue. Enter the information below which will be sent to the catalogue administrator. You will be notified of their decision by email.

    +

    You are requesting access to the @Model.CatalogueName catalogue. Enter the information below which will be sent to the catalogue administrator. You will be notified of their decision by email.

    - - - - - - - - - -
    Name:@Model.CurrentUser.FirstName @Model.CurrentUser.LastName
    Email:@Model.CurrentUser.EmailAddress
    + + + + + + + + + +
    Name:@Model.CurrentUser.FirstName @Model.CurrentUser.LastName
    Email:@Model.CurrentUser.EmailAddress
    -
    -
    - Enter your role, place of work, professional body number (if applicable) and information on why you are requesting access to this catalogue. -
    +
    +
    + Enter your role, place of work, professional body number (if applicable) and information on why you are requesting access to this catalogue. +
    - -
    -
    + +
    +
    - - - - - - - - @if (Model.CatalogueAccessRequest != null) - { - - - - } + + + + + + + + @if (Model.CatalogueAccessRequest != null) + { + + + + } -
    - Cancel - -
    - } +
    + + @if (Model.CatalogueAccessRequest != null && Model.CatalogueAccessRequest.Status == CatalogueAccessRequestStatus.Pending) + { + Cancel + + } + else + { + Cancel + + }
    + }
    +
    \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/Home/Contactus.cshtml b/LearningHub.Nhs.WebUI/Views/Home/Contactus.cshtml index 83f69b5eb..a91205c49 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/Contactus.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/Contactus.cshtml @@ -31,9 +31,9 @@
  • -

    +

    Support site -

    +

    Visit our support site for help on using the Learning Hub.

    @@ -44,9 +44,9 @@
  • -

    +

    Support team -

    +

    Complete our form to ask the support team for help.

    @@ -58,9 +58,9 @@
  • -

    +

    Share feedback -

    +

    Share your feedback to help us improve the platform.

    @@ -71,9 +71,9 @@
  • -

    +

    Contribute to user research -

    +

    Influence the future development of the Learning Hub.

    diff --git a/LearningHub.Nhs.WebUI/Views/Home/_CmsVideo.cshtml b/LearningHub.Nhs.WebUI/Views/Home/_CmsVideo.cshtml index 1b9433b83..bfa65821f 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/_CmsVideo.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/_CmsVideo.cshtml @@ -1,11 +1,11 @@ @using LearningHub.Nhs.Models.Content @model PageSectionDetailViewModel @{ - string mkPlayerLicence = (string)ViewData["mkPlayerLicenceKey"]; - var scheme = Context?.Request?.Scheme ?? "undefined"; - var host = Context?.Request?.Host; - var path = Context?.Request?.Path ?? "undefined"; - var requestURL = $"{scheme}://{host}{path}"; + string mkPlayerLicence = (string)ViewData["mkPlayerLicenceKey"]; + var scheme = Context?.Request?.Scheme ?? "undefined"; + var host = Context?.Request?.Host; + var path = Context?.Request?.Path ?? "undefined"; + var requestURL = $"{scheme}://{host}{path}"; } @@ -55,130 +55,161 @@ \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCountry.cshtml b/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCountry.cshtml index 2ad51ede1..0f8436e71 100644 --- a/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCountry.cshtml +++ b/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCountry.cshtml @@ -1,6 +1,7 @@ @using LearningHub.Nhs.WebUI.Models.UserProfile @model Tuple @{ + ViewData["DisableValidation"] = true; ViewData["Title"] = "My Account - Change country"; var errorHasOccurred = !ViewData.ModelState.IsValid; } diff --git a/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCurrentRole.cshtml b/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCurrentRole.cshtml index 40938608d..5cde300d8 100644 --- a/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCurrentRole.cshtml +++ b/LearningHub.Nhs.WebUI/Views/MyAccount/ChangeCurrentRole.cshtml @@ -1,97 +1,97 @@ @model LearningHub.Nhs.WebUI.Models.UserProfile.UserJobRoleUpdateViewModel @{ - ViewData["Title"] = "Update Current Role"; - var errorHasOccurred = !ViewData.ModelState.IsValid; + ViewData["DisableValidation"] = true; + ViewData["Title"] = "Update Current Role"; + var errorHasOccurred = !ViewData.ModelState.IsValid; }